1. 概述
Docker 是一个开源项目,它使得开发者和系统管理员可以轻松地在容器中部署应用、任务或服务。容器技术允许您将应用及其依赖环境打包成一个轻量级、可移植的容器中,这样可以确保它在任何 Linux 机器上无缝运行,无论是 物理机、虚拟机、云提供商平台还是个人电脑。Docker 使用简单的命令行工具和一系列APIs,提供了一个高效的方式来管理容器的生命周期,包括构建、发布、运行、更新和停止容器。
在本文中,我们将探讨 Docker CLI 的基本用法,包括如何使用命令来查找、拉取、推送、导出、加载镜像,以及如何创建容器、进行文件拷贝、数据卷挂载和容器管理等操作。通过学习和掌握这些基本用法,用户可以更好地利用 Docker CLI 来管理他们的容器化应用,提高工作效率和便捷性。
通过本文的介绍和实例操作,读者将能够全面了解 Docker CLI 的功能和用法,从而更好地利用 Docker 技术来构建、部署和管理他们的应用程序。Docker CLI 的强大功能和灵活性将为用户带来更高效的开发和部署体验,为现代软件开发提供了重要的支持和工具。
2. 镜像
2.1 Docker Hub
Docker Hub是用于存储、分享和管理Docker容器镜像的在线平台,为Docker社区提供了一个集中存储和共享容器镜像的地方。
如果在需要在Docker Hub存储发布自己的镜像,需要注册一个Docker Hub账户。首先,需要在Docker Hub上创建一个账户。这可以通过访问Docker Hub网站(https://hub.docker.com/)并点击"Sign UP"按钮来完成。
当然你也可以选择使用GitHUb等第三方工具进行注册/登陆:
如果使用第三方注册,首次登陆后可以在下面的页面修改你的密码:
依据邮件完成密码更改即可。
2.2 镜像的查找
在Docker中,你可以使用docker search
命令来查找Docker Hub中的镜像:
docker search <key-works>
其中:
- 表示关键词。
例如,如果查找与Ubuntu相关的镜像,可以运行以下命令:
docker search ubuntu
2.3 镜像的拉取
要拉取一个Docker镜像,可以使用docker pull
命令,例如:
docker pull ubuntu
上述命令将从Docker Hub拉取官方的Ubuntu镜像。你可以替换"ubuntu"为你需要的其他镜像名称。
你可以通过“:tag
”指定标签来选择不同的版本的镜像。例如,如果拉取Ubuntu 20.04版本的镜像,可以运行以下命令:
docker pull ubuntu:20.04
或者直接使用“latest”标签来拉取最新版本的镜像:
docker pull ubuntu:latest
如果不指定版本标签,Docker将默认拉取最新的版本。
要查看已经拉取到本地的镜像,可以使用docker images
命令:
docker images
从截图的示例中可以看到,当前拉取过3个镜像,以及各自的相关参数信息。
2.4 镜像的推送
镜像推送需要先执行登陆命令:
docker login
如果你想将自己创建的Docker镜像上传到Docker Hub,可以使用docker push
命令。首先,构建你的镜像,然后使用docker push
将其上传到Docker Hub。例如:
docker build -t <image-name>:tag . docker push <image-name>:tag
其中:
- :表示镜像名;
- tag:表示镜像的标签(可选)。
2.5 导出镜像为文件
要导出一个 Docker 镜像为文件,你可以使用 docker save
命令。具体的步骤如下:
查看可用镜像:
首先,你可以运行以下命令来查看已安装的 Docker 镜像列表:
docker images
- 这将列出所有已经下载或构建的 Docker 镜像。记下你想要导出的镜像的名称和标签。
- 导出 Docker 镜像为文件:
使用docker save
命令导出镜像为文件。语法如下:
docker save -o <输出文件名.tar> <镜像名称:标签>
<输出文件名.tar>
:指定导出的文件名,通常使用.tar
扩展名。<镜像名称:标签>
:指定要导出的镜像的名称和标签。
例如,如果你要导出一个名为 myapp
,标签为 v1.0
的镜像到名为 myapp_v1.0.tar
的文件中,可以运行以下命令:
docker save -o myapp_v1.0.tar myapp:v1.0
- 这将创建一个名为
myapp_v1.0.tar
的文件,其中包含了myapp:v1.0
镜像的所有文件和元数据。 - 确认导出:
导出过程完成后,你可以确认文件已成功创建,位于当前工作目录中。你可以运行 ls
命令来查看:
ls -l myapp_v1.0.tar
- 这将列出文件的详细信息,包括文件大小。
现在,你已经成功将 Docker 镜像导出为一个 .tar
文件。你可以将这个文件传输到其他机器或存档以备将来使用。要在其他机器上导入这个镜像,可以使用 docker load
命令。例如:
docker load -i myapp_v1.0.tar
这将导入镜像并使其可在新机器上运行。希望这可以帮助你完成 Docker 镜像的导出操作。
2.6 将镜像文件加载到Docker
本节和上一节介绍的内容互为逆过程。
要将 Docker 镜像文件加载到 Docker,你可以使用 docker load
命令。以下是详细的步骤:
- 将镜像文件复制到目标机器:
将之前导出的 Docker 镜像文件(通常是一个 .tar
文件)复制到目标机器上。你可以使用 scp
、rsync
或其他文件传输工具来进行复制。
- 加载 Docker 镜像文件:
在目标机器上,使用 docker load
命令来加载镜像文件。语法如下:
docker load -i <镜像文件名.tar>
<镜像文件名.tar>
:指定要加载的镜像文件的路径和名称。
例如,如果你要加载名为 myapp_v1.0.tar
的镜像文件,可以运行以下命令:
docker load -i myapp_v1.0.tar
这将从文件 myapp_v1.0.tar
中加载镜像到 Docker。
确认加载:
加载完成后,你可以运行以下命令来验证镜像是否已成功加载到 Docker:
docker images
- 这将列出目标机器上已加载的所有 Docker 镜像,包括你刚刚加载的镜像。
2.7 镜像删除
要删除 Docker 镜像,你可以使用 docker rmi
命令。以下是如何删除 Docker 镜像的具体步骤:
- 查看已安装的镜像:
在执行删除操作之前,你可以运行以下命令来查看已安装的 Docker 镜像列表:
docker images
- 这将列出所有已下载或构建的 Docker 镜像,以及它们的名称、标签、大小等信息。确定你想要删除的镜像的名称和标签。
- 删除 Docker 镜像:
使用docker rmi
命令来删除镜像。语法如下:
docker rmi <镜像名称:标签>
<镜像名称:标签>
:指定要删除的镜像的名称和标签。
例如,如果要删除名为 myapp
,标签为 v1.0
的镜像,可以运行以下命令:
docker rmi myapp:v1.0
如果要删除多个镜像,可以在命令中列出它们,例如:
docker rmi myapp:v1.0 myapp:v2.0
或者,如果要删除所有没有被容器使用的镜像,可以运行以下命令:
docker image prune -a
- 这将删除所有未被容器使用的镜像,包括没有标签的镜像。
- 确认删除:
老规矩,删除完成后,再次运行docker images
命令来确认是否已成功删除了镜像。被删除的镜像将不再出现在列表中。
3. 容器
3.1 由镜像创建容器
类比于VMWare
由镜像创建容器可以类比于 VMWare 新建虚拟机时需要从选择一个系统镜像开始:
只不过Docker中的镜像管理起来更加方便,既可以从一个Dcocker镜像文件导入Docker,也可以直接从Docker Hub拉取。
Docker Run 命令解析
docker run
命令用于创建和运行 Docker 容器。这个命令非常强大,有许多可用选项,以满足不同的需求。以下是对 docker run
命令以及其可用选项的全面解析:
docker run [选项] <镜像名称:标签> [命令] [参数]
选项
:用于配置容器的各种选项。<镜像名称:标签>
:指定要使用的 Docker 镜像的名称和标签。命令
:要在容器内部执行的命令(覆盖镜像中的默认命令)。参数
:传递给命令的参数。
以下是一些常用的 docker run
命令选项:
-d
或--detach
:在后台模式下运行容器。--name <容器名称>
:为容器指定一个名称。-p <主机端口>:<容器端口>
:将主机端口映射到容器端口。-v <主机目录>:<容器目录>
:将主机目录挂载到容器目录,创建数据卷。-e <环境变量>
:设置环境变量。--network <网络模式>
:指定容器的网络模式。--rm
:容器退出后自动删除容器。-i
:交互式模式,通常与-t
一起使用。-t
:为容器分配一个伪终端(TTY)。
除了这些常见选项之外,还有许多其他选项,可以根据需要进一步配置容器。以下是一些其他常用选项:
--hostname
:设置容器的主机名。--user
:指定容器内的用户。--link
:连接到其他容器。--volume-driver
:指定容器的数据卷驱动程序。--dns
:设置容器的 DNS 服务器。--privileged
:授予容器特权,以便执行特定的操作。--restart
:在容器退出时自动重启容器。--cap-add
和--cap-drop
:添加或删除容器的 Linux 内核功能。--device
:允许容器访问主机上的设备。--ulimit
:设置容器的资源限制。
要了解有关 docker run
命令的更多选项和详细信息,请参阅 Docker 官方文档或运行以下命令来查看帮助:
docker run --help
使用 docker run
命令可以根据不同的场景和需求创建和运行容器,定制化程度非常高,因此熟悉其可用选项和用法对于有效使用 Docker 非常重要。
基本示例:
假设我们已经使用pull命令拉取了一个名为nginx的docker镜像。现在使用 docker run
命令部署一个支持HTTP和HTTPS协议的Nginx网站容器。
docker run -d --name my-nginx-container -p 80:80 -p 443:443 --network bridge nginx
-network bridge 部分可以省略,因为在默认情况下,Docker容器会使用桥接网络模式。
这个命令将创建并在后台运行一个名为my-nginx-container的Nginx容器,该容器支持HTTP和HTTPS协议,并将主机的端口80和443映射到容器内的相应端口。容器将使用默认的桥接网络模式,允许从主机访问Nginx网站。
示例:创建tensorflow容器
tensorflow 是一个Google提供的张量运算库,常用于机器学习相关任务中,使用Docker是其最简单的环境部署方式。
下载 TensorFlow Docker 镜像
官方 TensorFlow Docker 镜像位于 tensorflow/tensorflow Docker Hub 仓库中。镜像发布以以下格式进行标记:
标签 | 描述 |
latest | TensorFlow CPU 二进制镜像的最新发布版本。默认选择。 |
nightly | TensorFlow 镜像的每夜构建版本。(不稳定) |
version | 指定 TensorFlow 二进制镜像的版本,例如:2.8.3 |
每个基本标签都有添加或更改功能的变体:
标签变体 | 描述 |
tag-gpu | 带有 GPU 支持的指定标签发布版本。 (见下文) |
tag-jupyter | 带有 Jupyter(包括 TensorFlow 教程笔记本)的指定标签发布版本。 |
可以同时使用多个变体。例如,以下命令将下载 TensorFlow 发布镜像到你的机器:
docker pull tensorflow/tensorflow # 最新稳定发布版本 docker pull tensorflow/tensorflow:devel-gpu # 夜间开发版带有 GPU 支持 docker pull tensorflow/tensorflow:latest-gpu-jupyter # 带有 GPU 支持和 Jupyter 的最新发布版
启动 TensorFlow Docker 容器
要启动一个已配置 TensorFlow 的容器,请使用以下命令形式:
docker run [-it] [--rm] [-p hostPort:containerPort] tensorflow/tensorflow[:tag] [command]
使用 CPU-only 镜像的示例
让我们使用最新的标记镜像来验证 TensorFlow 安装。Docker 在首次运行时会下载新的 TensorFlow 镜像:
docker run -it --rm tensorflow/tensorflow \ python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"
可以看到,在上面运行的 docker run 命令中:
1.-it: 这是两个选项的组合,用于指定在容器内开启一个交互式终端(-i 表示交互式,-t 表示为终端分配一个伪终端)。这使得用户可以与容器进行交互,例如在容器内执行命令;
2.--rm: 这是一个选项,它告诉 Docker 在容器退出时自动删除容器。这有助于确保容器不会在退出后留下残留的实例;
3.tensorflow/tensorflow: 这是要运行的 Docker 镜像的名称。在这种情况下,它是 TensorFlow 官方镜像,用于运行 TensorFlow 环境;
4.python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))": 这是在容器内执行的实际命令。它启动了一个 Python 解释器,并在其中运行一行 Python 代码。具体地说,它导入了 TensorFlow 库,生成一个包含随机数的矩阵,然后计算这个矩阵的总和并将结果打印出来
让我们演示一些更多的 TensorFlow Docker 配方。在 TensorFlow 配置的容器内启动一个 bash shell 会话:
docker run -it tensorflow/tensorflow bash
这个命令中:bash
: 这是在容器内执行的实际命令。它启动了一个bash shell会话,让用户可以在容器内执行命令和操作容器的文件系统。
在容器内,可以启动一个 Python 会话并导入 TensorFlow。
要在容器内运行在主机上开发的 TensorFlow 程序,请挂载主机目录并更改容器的工作目录(-v hostDir:containerDir -w workDir):
docker run -it --rm -v $PWD:/tmp -w /tmp tensorflow/tensorflow python ./script.py
这个命令的作用是创建一个交互式容器,使用TensorFlow官方镜像,并将当前主机的工作目录挂载到容器中的 /tmp 目录。然后,容器内启动一个Python解释器并运行 ./script.py 脚本,允许用户在容器内执行与TensorFlow相关的Python代码。一旦命令执行完毕,由于使用了 --rm 选项,容器将被自动删除,保持环境整洁。其中:
-it: 这是两个选项的组合,用于指定交互式终端。 -i 表示允许交互式输入,-t 表示为容器分配一个伪终端,使得用户可以与容器进行交互。
--rm: 这是一个选项,它告诉Docker在容器退出时自动删除容器。这有助于确保容器不会在退出后留下残留的实例。
-v $PWD:/tmp: 这是一个选项,用于将当前主机的工作目录 ($PWD) 挂载到容器内的 /tmp 目录。这样做可以让容器访问主机文件系统中的文件,并在容器内进行操作。
-w /tmp: 这是一个选项,用于设置容器的工作目录为 /tmp,这是上一步中挂载的目录。
tensorflow/tensorflow: 这是要运行的Docker镜像的名称,这里是TensorFlow官方镜像。
python ./script.py: 这是在容器内执行的实际命令。它启动了一个Python解释器,并运行 ./script.py 脚本。这个脚本应该位于容器内的工作目录 /tmp 中,由于上面的挂载操作,它实际上是主机文件系统中的 ./script.py。
当容器内创建的文件暴露给主机时,可能会出现权限问题。通常最好在主机系统上编辑文件。
使用 TensorFlow 的每夜构建版本启动 Jupyter Notebook 服务器:
docker run -it -p 8888:8888 tensorflow/tensorflow:nightly-jupyter
按照说明操作并在主机的网络浏览器中打开 URL:http://127.0.0.1:8888/?token=…
GPU 支持
Docker 是在 GPU 上运行 TensorFlow 的最简单方式,因为主机机器只需安装 NVIDIA® 驱动程序(不需要安装 NVIDIA® CUDA® Toolkit)。
安装 Nvidia 容器工具包以在 Docker 中添加 NVIDIA® GPU 支持。nvidia-container-runtime 仅适用于 Linux。有关详细信息,请参阅 nvidia-container-runtime 平台支持 FAQ。
检查是否存在 GPU:
lspci | grep -i nvidia
验证你的 nvidia-docker 安装:
docker run --gpus all --rm nvidia/cuda nvidia-smi
注意:nvidia-docker v2 使用 --runtime=nvidia 替代了 --gpus all。nvidia-docker v1 使用 nvidia-docker 别名,而不是 --runtime=nvidia 或 --gpus all 命令行标志。
使用启用 GPU 的镜像的示例
下载并运行启用 GPU 的 TensorFlow 镜像(可能需要几分钟):
docker run --gpus all -it --rm tensorflow/tensorflow:latest-gpu \ python -c "import tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))"
设置启用 GPU 的镜像可能需要一些时间。如果反复运行基于 GPU 的脚本,你可以使用 docker exec 重用容器。
使用最新的 TensorFlow GPU 镜像在容器内启动一个 bash shell 会话:
docker run --gpus all -it tensorflow/tensorflow:latest-gpu bash
成功:TensorFlow 现在已安装。请阅读教程以开始使用。
示例:创建mysql容器
和 Tenflow、Nginx等一样,MySQL同样可以基于Docker安装。官方提供了已经部署好MySQL数据库的Docker镜像。
步骤 1:拉取MySQL镜像
使用以下命令从Docker Hub上拉取MySQL官方镜像:
docker pull mysql:latest
这将下载最新版本的MySQL镜像到你的本地系统。
步骤 2:创建MySQL容器
使用以下命令创建一个MySQL容器。在此示例中,我们将容器命名为 mysql-container
,设置了用户的密码为 my-secret-pw
,并将主机的端口3306映射到容器的端口3306。
docker run -d --name mysql-container -e MYSQL_ROOT_PASSWORD=my-secret-pw -p 3306:3306 mysql:latest
这将创建并在后台运行MySQL容器。
这个命令中,创建一个MySQL服务器容器,使其以后台模式运行。容器被命名为 mysql-container,并设置了 MySQL root 用户的密码为 my-secret-pw。此外,主机的端口 3306 被映射到容器的端口 3306,这样可以通过主机上的端口来访问容器内的 MySQL 服务器。这个容器将使用官方MySQL镜像,运行最新版本的 MySQL 服务器。其中:
-d: 这个选项表示在后台模式下运行容器,容器将在后台运行而不会阻塞终端;
--name mysql-container: 这个选项为容器指定了一个名称,这里是 mysql-container,你可以根据需要自定义容器名称;
-e MYSQL_ROOT_PASSWORD=my-secret-pw: 这个选项通过环境变量设置MySQL服务器的root用户密码。在这个示例中,密码被设置为 my-secret-pw,你可以根据需要选择不同的密码;
-p 3306:3306: 这个选项将主机的端口3306映射到容器的端口3306。容器内的MySQL服务器默认监听在端口3306上,这使得可以通过主机上的端口 3306 访问容器内的MySQL服务器;
mysql:latest: 这是要运行的 Docker 镜像的名称。在这个示例中,我们使用的是 MySQL 的官方镜像, latest 表示使用最新版本的MySQL镜像。
步骤 3:连接到MySQL服务器
你可以使用MySQL客户端连接到MySQL服务器。在终端中运行以下命令,使用root用户和之前设置的密码 my-secret-pw
连接到MySQL服务器:
mysql -h 127.0.0.1 -u root -p
输入密码 my-secret-pw
后,你将成功连接到MySQL服务器。
可以看到,在截图中,我拉取了官方的mysql镜像,运行它时使用“-e MYSQL_ROOT_PASSWORD=123456”设置环境变量MYSQL_ROOT_PASSWORD的值为123456设置MySQL服务器的root用户密码。并且暴露了mysql的默认端口(3306),方便容器外部使用它。
通过exec进入到容器系统,在容器内部,使用 mysql -h 127.0.0.1 -u root -p并输入之前设置的密码成功登陆了mysql。
3.2 容器和宿主机之间文件拷贝
从宿主机到容器的复制
使用以下命令将宿主机上的文件复制到运行中的容器中(<容器名称或ID>
和 <宿主机文件路径>
根据实际情况替换):
docker cp <宿主机文件路径> <容器名称或ID>:<容器目标路径>
示例:
docker cp /path/to/host/file.txt my-container:/tmp/file.txt
从容器到宿主机的复制
使用以下命令将容器内的文件复制到宿主机(<容器名称或ID>
和 <容器文件路径>
根据实际情况替换):
docker cp <容器名称或ID>:<容器文件路径> <宿主机目标路径>
示例:
docker cp my-container:/tmp/file.txt /path/to/host/
3.3 使用数据卷挂载
除了上一小节介绍的使用 docker cp
命令进行文件复制,另一种常见的文件在容器和宿主机之间传递方法是通过 数据卷挂载 来实现。
你可以在容器中创建数据卷,并将宿主机上的目录挂载到该数据卷上。这样,容器和宿主机可以共享文件。
创建数据卷:
使用以下命令创建一个数据卷:
docker volume create my-volume
运行容器并挂载数据卷:
运行容器时,使用 -v
选项将数据卷挂载到容器的指定路径上(<宿主机目录>
和 <容器目标路径>
根据实际情况替换):
docker run -d --name my-container -v my-volume:<容器目标路径> image-name
例如:
docker run -d --name my-container -v my-volume:/app my-image
在容器和宿主机之间传递文件:
现在,你可以在宿主机上将文件复制到数据卷挂载的目录中,然后容器内的应用程序可以访问它们。
3.4 共享目录
共享目录也是一种在宿主机和容器之间创建共享目录来实现文件传递的方式。这可以通过将宿主机目录挂载到容器中来实现,类似于数据卷挂载。
- 运行容器并挂载共享目录:
在运行容器时,使用 -v
选项将宿主机的目录挂载到容器的指定路径上(<宿主机目录>
和 <容器目标路径>
根据实际情况替换):
docker run -d --name my-container -v /path/to/host/directory:/container/target/directory image-name
例如:
docker run -d --name my-container -v /host-folder:/container-folder my-image
- 在容器和宿主机之间传递文件:
您可以在宿主机上将文件复制到共享目录,然后容器内的应用程序可以访问它们。
这些是在Docker容器和宿主机之间进行文件传递的几种常见方法。您可以根据具体的需求选择最适合您的方法。无论使用哪种方法,都需要谨慎处理文件权限和路径,以确保文件能够正确传递并在容器内外进行访问。
3.5 容器管理
容器管理的很多命令都提到过了,比如docker start
、docker stop
等等,这里做一些回顾和补充。
列出容器
要列出所有正在运行的容器,可以使用docker ps
命令:
docker ps
要列出包括停止的容器在内的所有容器,可以添加-a
选项:
docker ps -a
查看容器日志
要查看容器的日志输出,可以使用docker logs
命令,后跟容器的名称或ID:
docker logs my-container
进入容器
要进入正在运行的容器的命令行终端,可以使用docker exec
命令:
docker exec -it my-container /bin/bash
其中:
-it
选项表示交互式终端。my-container
是容器的名称或ID。/bin/bash
是要运行的shell。
停止容器
要停止一个正在运行的容器,可以使用docker stop
命令,后跟容器的名称或ID:
docker stop my-container
启动容器
要启动一个已停止的容器,可以使用docker start
命令,后跟容器的名称或ID:
docker start my-container
删除容器
要删除一个容器,可以使用docker rm
命令,后跟容器的名称或ID:
docker rm my-container
清理无用容器
Docker中有时会留下未使用的容器。要清理这些无用容器,可以使用以下命令:
docker container prune
监视容器
要监视容器的资源使用情况,可以使用docker stats
命令,后跟容器的名称或ID:
docker stats my-container
4. 结论
Docker 已经成为现代软件开发和运维的一个重要工具。它通过容器化技术,提供了一种高效、一致和可移植的方式来部署和管理应用。通过学习本文,读者可以掌握如何使用 Docker CLI 的基本用法来有效地管理 Docker 容器和镜像的管理,实现快速部署和运行应用程序的目的。
Docker CLI 提供了丰富的命令和选项,使得用户可以轻松地执行各种操作,如查找镜像、拉取镜像、推送镜像、创建容器、文件拷贝、数据卷挂载等。这些功能和操作能够帮助用户更好地利用 Docker 技术,提高工作效率和便捷性。
总的来说,掌握 Docker CLI 的基本用法对于开发人员和系统管理员来说是非常重要的。通过深入了解和实践这些命令,用户可以更好地利用 Docker 技术来构建、部署和管理他们的应用程序,从而提高开发和部署的效率,加快应用交付的速度。希望本文能够帮助读者更好地理解和应用 Docker CLI,为其日常工作带来便利和效益。
如果你对Docker技术还不是很了解,可以考虑从本系列第一篇文章开始阅读:《Docker技术概论(1):Docker与虚拟化技术比较》。
如果你觉得本文对你有所帮助,请在文章处点赞支持。 虽然这不会使我从中获得经济利益,但是你的赞是继续分享的巨大动力&^_^&