docker 启动images id Docker 启动镜像_docker查看镜像版本

前几天写了一篇文章《前端部署发展史》,前端部署的发展离不开 DevOps 的发展,而 DevOps 又得益于 Docker 的发展。因此,前端掌握 Docker 也势在必行,何况它又不是很难。Docker 使应用部署更加轻量,可移植,可扩展。更好的环境隔离也更大程度地避免了生产环境与测试环境不一致的巨大尴尬。由于 Docker 轻便可移植的特点也极大促进了 CI/CD 的发展。术语


docker 启动images id Docker 启动镜像_docker查看镜像版本_02

Docker 的架构图如下:


docker 启动images id Docker 启动镜像_docker 启动镜像_03

从图中可以看出几个组成部分:


  • Docker Client:即 Docker 命令行工具
  • Docker Host:宿主机,Docker Daemon 的运行环境服务器
  • Docker Daemon:Docker 的守护进程,Docker Client 通过命令行与 Docker Daemon 交互
  • Container:最小型的一个操作系统环境,可以对各种服务以及应用容器化
  • Image:镜像,可以理解为一个容器的模板配置,通过一个镜像可以启动多个容器
  • Registry:镜像仓库,存储大量镜像,可以从镜像仓库拉取和推送镜像

安装 Docker


docker 启动images id Docker 启动镜像_docker查看镜像版本_02

参考在 CentOS 上安装 Docker 的官方文档:https://docs.docker.com/install/linux/docker-ce/centos/以下是在 CentOS 上安装 Docker 的命令示例过程。安装依赖:

$ yum install -y yum-utils device-mapper-persistent-data lvm2

添加 Docker 的yum镜像源,如果在国内,添加阿里云的镜像源。

# 安装 docker 官方的镜像源
 
   
  
$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
 
   
  
# 如果在国内,安装阿里云的镜像
 
   
  
$ yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo


安装指定版本的 Docker 并且启动服务。

# 安装 Docker
 
   
  
$ yum install -y docker-ce
 
   
  
# 安装指定版本号的 Docker,以下是 Kubernetes 官方推荐的 Docker 版本号(此时,Kubernetes 的版本号在 v1.16)
 
   
  
$ yum install -y docker-ce-18.06.2.ce
 
   
  
$ systemctl enable docker
 
   
  
Created symlink from /etc/systemd/system/multi-user.target.wants/docker.service to /usr/lib/systemd/system/docker.service.
 
   
  
$ systemctl start docker

当 Docker 安装成功后,可以使用以下命令查看版本号。

$ docker --version
 
   
  
Docker version 18.06.2-ce, build 6d37f41
 
   
  
# 查看更详细的版本号信息
 
   
  
$ docker version
 
   
  
# 查看 Docker 的详细配置信息
 
   
  
$ docker info


守护进程配置dockerd 是 Docker 的守护进程,dockerd 可以通过配置文件进行配置,在 Linux 下的配置文件位置在 /etc/docker/daemon.json,更详细内容可以参考官方文档。日志引擎为 json-file,对日志结构化,结合合适的日志系统,方便定位日志。

存储引擎为 overrlay2。



$ mkdir /etc/docker
 
   
  
# 设置 docker daemon
 
   
  
$ cat > /etc/docker/daemon.json <<EOF
 
   
  
{
 
   
  
 "exec-opts": ["native.cgroupdriver=systemd"],
 
   
  
 "log-driver": "json-file",
 
   
  
 "log-opts": {
 
   
  
 "max-size": "100m"
 
   
  
 },
 
   
  
 "storage-driver": "overlay2",
 
   
  
 "storage-opts": [
 
   
  
 "overlay2.override_kernel_check=true"
 
   
  
 ]
 
   
  
}
 
   
  
EOF
 
   
  
# 重启 docker
 
   
  
$ systemctl daemon-reload
 
   
  
$ systemctl restart docker


底层原理


docker 启动images id Docker 启动镜像_docker查看镜像版本_02

Docker 底层使用了一些 Linux 内核的特性,大概有 Namespace,CGroups 和 UFS。

NamespaceDocker 使用 Linux Namespace 构建隔离的环境,它由以下 Namespace 组成。


  • pid:隔离进程
  • net:隔离网络
  • ipc:隔离 IPC
  • mnt:隔离文件系统挂载
  • uts:隔离 hostname
  • user:隔离 uid/gid

Control Groups也叫 CGroups,限制资源配额,比如某个容器只能使用 100M 内存。

Union File SystemsUnionFS 是一种分层、轻量级并且高性能的文件系统,支持对文件系统的修改作为一次提交来一层层的叠加。Docker 的镜像与容器就是分层存储,可用的存储引擎有 aufs,overlay 等。关于分层存储的详细内容可以查看官方文档:https://docs.docker.com/storage/storagedriver/。镜像


docker 启动images id Docker 启动镜像_docker查看镜像版本_02

镜像是一份用来创造容器的配置文件,而容器可以视作最小型的一个操作系统。Docker 的镜像和容器都使用了 UnionFS 做分层存储,镜像作为只读层是共享的,而容器在镜像之上附加了一层可写层,最大程度地减少了空间的浪费,详见下图:


docker 启动images id Docker 启动镜像_docker_07

镜像仓库与拉取大部分时候,我们不需要自己构建镜像,我们可以在官方镜像仓库拉取镜像。可以简单使用命令 docker pull 拉取镜像。拉取镜像后可以使用 docker inspect 查看镜像信息。

# 加入拉取一个 node:alpine 的镜像
 
   
  
$ docker pull node:alpine
 
   
  
# 查看镜像信息
 
   
  
$ docker inspect node:alpine
 
   
  
# 列出所有镜像
 
   
  
$ docker images
 
   
  
REPOSITORY TAG IMAGE ID CREATED SIZE
 
   
  
node alpine f20a6d8b6721 13 days ago 105MB
 
   
  
mongo latest 965553e202a4 2 weeks ago 363MB
 
   
  
centos latest 9f38484d220f 8 months ago 202MB



构建镜像与发布但并不是所有的镜像都可以在镜像仓库中找到,另外我们也需要为我们自己的业务应用去构建镜像。使用 docker build 构建镜像,docker build 会使用当前目录的 Dockerfile 构建镜像,至于 Dockerfile 的配置,参考下节。-t 指定标签:

# -t node-base:10: 镜像以及版本号
 
   
  
# .: 指当前路径
 
   
  
$ docker build -t node-base:10 .


当构建镜像成功后可以使用 docker push 推送到镜像仓库。Dockerfile


docker 启动images id Docker 启动镜像_docker查看镜像版本_02

在使用 Docker 部署自己应用时,往往需要自己构建镜像。Docker 使用 Dockerfile 作为配置文件构建镜像,简单看一个 Node 应用构建的 Dockerfile。


FROM node:alpine
 
   
  
ADD package.json package-lock.json /code/
 
   
  
WORKDIR /code
 
   
  
RUN npm install --production
 
   
  
ADD . /code
 
   
  
CMD npm start


FROM基于一个旧有的镜像,格式如下:


FROM  [AS ]
 
   
  
# 在多阶段构建时会用到
 
   
  
FROM [:<tag>] [AS ]


ADD把目录,或者 url 地址文件加入到镜像的文件系统中。


ADD [--chown=<user>:<group>] ...


RUN执行命令,由于 UFS,它会在当前镜像的顶层新增一层。


RUN 


CMD指定容器如何启动。一个 Dockerfile 中只允许有一个 CMD。


# exec form, this is the preferred form
 
   
  
CMD ["executable","param1","param2"] 
 
   
  
# as default parameters to ENTRYPOINT
 
   
  
CMD ["param1","param2"]
 
   
  
# shell form
 
   
  
CMD command param1 param2


容器


docker 启动images id Docker 启动镜像_docker查看镜像版本_02

镜像与容器的关系,类似于代码与进程的关系。


  • docker run 创建容器
  • docker stop 停止容器
  • docker rm 删除容器

创建容器基于 Nginx 镜像创建一个最简单的容器:启动一个最简单的 http 服务。使用 docker run 来启动容器,docker ps 查看容器启动状态。


$ docker run -d --name nginx -p 8888:80 nginx:alpine
 
   
  
$ docker ps -l
 
   
  
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
 
   
  
404e88f0d90c nginx:alpine "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 0.0.0.0:8888->80/tcp nginx
 
   
  
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES


其中:


  • -d:启动一个 daemon 进程
  • --name:为容器指定名称
  • -p host-port:container-port:宿主机与容器端口映射,方便容器对外提供服务
  • nginx:alpine:基于该镜像创建容器

此时在宿主机使用 curl 测试容器提供的服务是否正常。


$ curl localhost:8888
 
   
  
DOCTYPE html>
 
   
  
Welcome to nginx!title>
 
   
  
 body {
 
   
  
 width: 35em;
 
   
  
 margin: 0 auto;
 
   
  
 font-family: Tahoma, Verdana, Arial, sans-serif;
 
   
  
 }
 
   
  
style>
 
   
  
head>
 
   
  
 
  Welcome to nginx!h1> 
  
If you see this page, the nginx web server is successfully installed and
 
   
  
working. Further configuration is required.p>
 
   
  
For online documentation and support please refer to
 
   
  
<a href="http://nginx.org/">nginx.org</a>.>
 
   
  
Commercial support is available at
 
   
  
<a href="http://nginx.com/">nginx.com</a>.p>
 
   
  
Thank you for using nginx.</em>p>
 
   
  
body>
 
   
  
html>


那如果要进入容器环境中呢?使用 docker exec -it container-name sh 命令。


$ docker exec -it nginx sh
 
   
  
/ #
 
   
  
/ #
 
   
  
/ #


容器管理docker ps 列出所有容器:


$ docker ps
 
   
  
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
 
   
  
404e88f0d90c nginx:alpine "nginx -g 'daemon of…" 4 minutes ago Up 4 minutes 0.0.0.0:8888->80/tcp nginx
 
   
  
498e7d74fb4f nginx:alpine "nginx -g 'daemon of…" 7 minutes ago Up 7 minutes 80/tcp lucid_mirzakhani
 
   
  
2ce10556dc8f redis:4.0.6-alpine "docker-entrypoint.s…" 2 months ago Up 2 months 0.0.0.0:6379->6379/tcp apolloserverstarter_redis_1

docker port 查看容器端口映射:

$ docker port nginx
 
   
  
80/tcp -> 0.0.0.0:8888

docker stats 查看容器资源占用:



$ docker stats nginx
 
   
  
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
 
   
  
404e88f0d90c nginx 0.00% 1.395MiB / 1.796GiB 0.08%