容器之路(2)-运行容器
环境选择及安装
当下定决心要学习容器的时候,最简单的就是搭个环境先体验体验。
但在开始之前,要大致了解一下容器是怎样的一种存在。
最早的时候,容器仅支持 Linux 平台,也就是说,要使用容器,必须得先有一台 Linux 机器,可以是虚拟机,然后在 Linux 内装一个容器引擎,例如 Docker ,你就可以使用容器了。
随着 Linux 容器变得异常火,Windows 也开始支持容器,但除非你有空想做研究,否则我是劝退的。
为了让普通用户能快速用上容器,Docker 推出了 Desktop 版本,简单来说就是在 Windows 或者 Mac 等非 Linux 平台上跑了一个封装好的 Linux 虚拟机,然后提供了易用的接口实现本地 shell 集成,用户直接在本地的命令行里就能使用 Docker 命令,无需 SSH 到 Linux 虚拟机中去。
为了尽量模拟生产环境,我建议还是自己装一台能连接互联网 Linux 虚拟机,然后再安装 Docker。安装的命令非常简单,参考 Docker 官方文档即可:
https://docs.docker.com/engine/install/
以 CentOS 为例,安装命令只有三条:
sudo yum install -y yum-utils
sudo yum-config-manager —add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
安装完成后,运行下列命令启动 docker:
sudo systemctl start docker
接着就可以使用容器了,运行 docker version 查看安装好的 Docker 版本:
运行第一个容器
直接复制粘贴下列命令,就可以运行起第一个容器了
docker run -d -p 8088:80 -e hostinfo=$HOSTNAME —restart=unless-stopped dyadin/avi-demo:v2
然后记录 Linux 的地址,在浏览器中访问 http://
启动命令的参数说明:
run:如其名字一样,运行容器,但实际上 run 可能包含多个后台的工作,比如先去查看指定的容器镜像本地存不存在,如果不存在会先从 Dockerhub 下载镜像,然后再运行容器;
-d :表示 detach,将容器在后台运行,只打印出容器 ID。如果不使用 -d 命令,会直接打印容器里进程的输出;
-p:将 Linux 的某个端口映射到容器内服务使用的端口,比如上述命令是将 Linux 的 8088 端口映射到了容器的 80 端口;
-e:指定一个环境变量,环境变量名为 hostinfo,内容为 Linux 节点的 $HOSTNAME 变量,目的是将 Linux 的主机名传递给容器来使用;
—restart=unless-stopped:重启策略,当容器停止之后应该如何操作,使用 unless-stopped 后,用户可以执行手动停止容器,其他情况发生都会自动重启容器;
dyadin/avi-demo:v2:表示容器镜像的名称,dyadin 是 dockerhub 上的用户名,avi-demo 则是镜像的名称,: 后面的 v2 表示镜像的版本。
是不是感觉很简单?一条命令就可以定义好应用需要的参数、端口如何暴露、重启策略、镜像的名称。
接着我们稍微深入一点,看看如何管理容器。
容器管理
管理的第一个场景就是如何知道容器是不是在运行,并查看它的日志。
在 Docker 下可以运行 docker ps 查看正在运行的容器,status 列会显示已经运行多久,记录第一列的 Container ID,未来查看容器的详细信息需要使用这个 ID(如果想要完整的命令输出,可以添加 —no-trunc 参数)。
接着运行 docker logs -f f11 即可实时查看容器的运行日志。在下方的示例中,可以看到一些浏览器访问日志。(注意,容器 ID 并不一定需要输完整,输入前面一小部分,能和其他容器区分开就行)
管理的第二个场景是如何停止、重启、启动容器。
在 Docker 下命令和传统的 Linux 命令有几分相似:
重启容器:
docker restart f11
停止容器:
docker stop f11
查看停止的容器:
docker ps -a
启动容器:
docker start f11
第三个最常用的场景,是进入到容器进行进一步排错/分析。
如果容器提供了 shell,可以使用下列命令进入容器:
docker exec -it f11 bash
命令参数如下:
exec :表示执行容器中的一条命令;
-it:其中 i 表示交互,t 表示 tty,可以理解为前台执行了一条命令,可以进行交互式操作;
f11:容器 ID;
bash:最终要执行的容器命令。(上述示例中使用的镜像中已经集成了 bash,所以可以使用 bash,一般社区的镜像很可能只有 sh 没有 bash)
一旦通过 shell 进入到容器后,可以执行容器中有的任意命令。比如在上述示例中执行了 ps 命令。
通过 ps 命令也可以看到这个容器非常轻量,运行的进程非常少。
数据持久化
在第一篇文章中我简单提到,在容器中如果要持久化保存用户数据,需要使用数据卷。数据卷的用法非常简单,很类似于 Linux 的磁盘 mount。
可能是因为一开始对于容器的定义就是短生命周期的,所以官方并没有什么手段给正在运行的容器挂载一个新的卷,社区虽然有办法在不影响容器(尤其是数据)的前提下挂载卷,但是… 太 geek 了放弃吧。
我们先运行下列两条命令停止并删除之前运行的容器:
docker stop f11
docker rm f11
接着运行下列命令将一个 Linux 本地路径挂载给容器,并启动容器:
docker run -d -p 8088:80 -e hostinfo=$HOSTNAME -v /tmp/test:/root/test —restart=unless-stopped dyadin/avi-demo:v2
在上述命令中,-v 表示 volume,即给容器挂载卷,源路径是 Linux 的一个本地路径”/tmp/test”,目标路径是容器中的 “/root/test”。
通过 docker ps 获取容器 ID:
通过下列命令查看容器挂载的卷:
docker inspect d3c6804dd107 -f ‘{{ .Mounts }}’
接着我们在 Linux 主机的 /tmp/test 目录下随便创建一个文件:
echo ThisIsATestFile>/tmp/test/a.txt
回到浏览器中,访问 http://
接着我们删除刚才的容器,再用同样的命令创建一个新的容器:
docker stop d3c
docker rm d3c
docker run -d -p 8088:80 -e hostinfo=$HOSTNAME -v /tmp/test:/root/test —restart=unless-stopped dyadin/avi-demo:v2
进行同样的访问测试,发现文件依然存在,也就是说容器的启停并不会影响数据卷中的内容。
最后我们再运行另一个容器,为了避免冲突需要使用不同的端口:
docker run -d -p 8089:80 -e hostinfo=$HOSTNAME -v /tmp/test:/root/test —restart=unless-stopped dyadin/avi-demo:v2
访问这个容器,内容和上一个容器一模一样,也就表明,多个容器可以同时挂载一个数据卷,同时都可以读这个数据卷:
这只是最简单的数据卷的用法,可谓非常静态和原始,另一个比较标准的用法则是先创建一个 volume,然后将此 volume 挂载给容器。方法如下:
docker volume create vol-1
docker run -d -p 8090:80 -e hostinfo=$HOSTNAME -v vol-1:/root/test —restart=unless-stopped dyadin/avi-demo:v2
要想查看容器数据卷的详情,可以运行下列命令:
docker inspect f30 -f ‘{{ .Mounts }}’
通过上述命令也可以发现,数据卷 vol-1 的路径在 /var/lib/docker/volumes/vol-1/_data ,也只是 Linux 的一个目录而已。
默认 Docker 的 root 路径是 /var/lib/docker/ ,可以通过 docker info 命令进行确认:
进入到这个路径 ls 一下,可以看到 Docker 几乎所有的用户数据均在这里。
再回到正文,我们可以通过上个章节学到的方法进入容器,在这个数据卷中创建一些文件:
docker exec -it f30 bash
for i in {1..5}; do echo “This Is Test File $i” > $i.txt; done
回到宿主机 Linux,在默认数据卷的路径下查看这些文件。效果和之前直接挂在宿主机的路径一模一样。
数据卷的内容就讲这么多。运行容器的基础命令也介绍完毕。
写到这里,读者应该对容器稍微有了具象的理解,并且可以简单地运行和管理容器。
如果想掌握更多 docker 的特性,直接在命令行输入 docker 回车就可看到所有支持的功能,随便挑一项功能,比如 docker image,再在后面加上 —help 查看子命令的介绍: