Docker每日一阅(5):Docker Container Run
0 回顾
- 查看运行容器的日志(
docker container logs [container id]
) - 关闭正在运行的容器(
docker container stop [container id]
) - 创建镜像(
docker container commit [container id]
/docker image build ...
) - 查看镜像的详细信息(
docker image inspect [image id]
)
0 任务描述
- 对docker image run有更深入的了解,包括
docker container run --name [container_name] [docker_image]
docker container run -d [docker_image]
docker container run -it [docker_image]
docker container run -p [host_ip]:[host_port]:[container_port] [docker_image]
docker container run -v [/host/volume/location]:[/container/storage] [docker_image]
docker container run --mount type=bind,source=[/host/volume/location],destination=[/container/storage] [docker_image]
docker container run --rm [docker_image]
1 docker image run
在前几天的文章中,我们已对docker run有了初步的了解与尝试。这里我们将跟全面地解读docker run的更多用法。
该命令的基本语法是:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
要运行一个容器,命令中只需包含它所基于的镜像:
docker run [docker_image name/id]
我们可以从本地存储的Docker镜像运行容器(比如可以先通过docker image list
查看本地的镜像列表)。如果镜像不在本地系统中,Docker会将其从registry中寻找匹配的镜像。
1.1 给运行的容器命名:--name [container_name] [docker_image]
如果我们直接在terminal中运行
docker container run alpine
Docker会自动生成一个容器名称,其中包含一个随机选择的数字和字母字符串(输入docker ps -a
,在NAMES这一栏我们看到epic_khorana
):
CONTAINER ID IMAGE COMMAND CREATED PORTS NAMES
1d3b855445e0 alpine "/bin/sh" 10 seconds ago epic_khorana
当然,我们也可以给容器一个自定义的命名,符合以下格式:
docker container run --name [container_name] [docker_image]
比如,
docker container run --name alpine_v2 alpine
输入docker ps -a
,在NAMES这一栏我们看到alpine_v2
:
CONTAINER ID IMAGE COMMAND CREATED PORTS NAMES
fa607d5f8e8d alpine "/bin/sh" 32 seconds ago alpine_v2
1.2 后台运行容器:-d [docker_image]
运行容器有两种方式:在attached mode(前台运行),或在detached mode(后台运行)。
默认情况下,Docker会以attached mode运行容器。这就意味着它会连接到terminal,在那里显示输出和消息。
但是,如果我们希望将容器和当前terminal分开,即后台运行容器,则可以在docker run后面加-d
:
docker container run -d [docker_image]
比如,如果我们在terminal中输入:
docker container run alpine ls -l
那么,我们会在terminal中看到容器被创建后执行ls -l
的结果,即:
total 56
drwxr-xr-x 2 root root 4096 Nov 24 09:20 bin
drwxr-xr-x 5 root root 340 Mar 12 03:39 dev
drwxr-xr-x 1 root root 4096 Mar 12 03:39 etc
但是,如果我们在terminal中输入:
docker container run -d alpine ls -l
我们会发现,terminal只返回了
59c59d0f17f0a65c431fb89d334b413ffcba4f83bd1e24f41f814eaa3b23ec6b
即,容器id。
1.3 运行交互模式:-it [docker_image] /bin/bash
这个在之前的博客中已有描述,这里就不再赘述了。我们可以在terminal中输入:
docker container run -it alpine
然后我们在terminal中就能看到自己进入了这个container。
/ #
1.4 发布容器端口:-p [host_ip]:[host_port]:[container_port] [docker_image]
当我们运行容器时,访问进程的唯一方法是从容器内部。如果要允许外部连接到容器,必须打开(发布)特定端口。我们可以在docker run后面加-p
:
docker container run -p [host_ip]:[host_port]:[container_port] [docker_image]
这里,[host_ip]
是可选的,一般不需要填写。比如:
docker container run -p 8080:80 alpine
这样一来,我们就将宿主端口8080和容器端口80绑定了,并打开了此端口。
1.5 卷挂载之Bind Mount形式:-v/--mount
Docker容器不会保存它们生成的数据。一旦这个过程结束,容器就会停止,里面的所有东西都会被移除。如果希望在容器停止后仍存储持久数据,则需要启用共享存储卷。
Docker 提供了三种不同的方式将数据从 Docker Host 挂载到 Docker 容器,并实现数据的读取和存储:volumes、bind mounts、tmpfs。这里我们只讲前两种。
bind mount自docker早期便开始为人们使用了,用于将host上的文件或目录被挂载到容器中。挂载时需要我们指定文件或目录在 host 上的完整路径。
这里有两种写法:
-
在docker run后面加
--volume/-v
;docker container run -v [/host/volume/location]:[/container/storage] [docker_image]
-
在docker run后面加
--mount
;docker container run --mount type=bind,source=[/host/volume/location],destination=[/container/storage] [docker_image]
如下为一个-v
的例子:
docker run -it -v $pwd/html:/html alpine
如下为一个--mount
的例子:
docker run -it --mount type=bind,source="$(pwd)"/html,target=/html alpine
当我们在terminal中输入了如上命令后,在路径$(pwd)/html
,如果本来没有html这个文件夹的话,系统会自动生成一个。在容器中也是一样。启动容器后,如果我们在容器中/html
路径下添加任何文件,在主机的对应路径下也会显示。哪怕最终我们将新建的容器删除,主机目录下的文件也不会被删除。
如果我们使用docker inspect
来查看Mounts有关信息,我们会看到
"Mounts": [
{
"Type": "bind",
"Source": "D:\\XXX\\MLOps/html",
"Destination": "/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
我们可以看到,这个Mount Type是bind,并且是读写挂载。
1.6 卷挂载之:Volume形式:-v/--mount
bind mount
形式指的是将host的自定义目录与容器的自定义目录bind在一起。而volume
形式则是基于host的Docker创建的volume与容器的自定义目录bind在一起。这个volume完全是由docker管理的。
我们可以用如下命令来创建一个卷:
docker volume create vol_1
让我们来查看这个新建的卷的信息docker volume inspect vol_1
,结果如下:
[
{
"CreatedAt": "2022-03-12T06:30:28Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/vol_1/_data",
"Name": "vol_1",
"Options": {},
"Scope": "local"
}
]
你能看到这个Mountpoint
在Win10系统中是不存在的,但如果我们使用的是Linux主机,是可以找到对应的位置的。我们也可以在Docker Desktop中查看所有的卷。
如果这时需要将这个卷与container绑定在一起,这里有两个例子:
-
在docker run后面加
--volume/-v
;docker run -v vol_1:/html alpine
-
在docker run后面加
--mount
;docker run --mount source=vol_1,target=/html alpine
我们再来inspect一下新建的容器:
"Mounts": [
{
"Type": "volume",
"Name": "vol_1",
"Source": "/var/lib/docker/volumes/vol_1/_data",
"Destination": "/html",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
我们会发现,mount type变成了volume。
1.7 容器运行完后自动删除:--rm [docker_image]
一旦容器完成需要执行的任务,它就会停止,但它所包含的文件系统仍保留在系统上。这个时候,如果我们希望容易一旦执行完指令后就自动删除,那么可以在docker run后面加--rm
:
docker container run --rm [docker_image]