其他
淘宝FED:前端也应该了解点 docker 知识 fed.taobao.org/blog/taofed… fed.taobao.org/blog/taofed…
守护进程
container要想保持运行,要有守护进程,Pid 0 还是 1? 如pm2
每个container有独立的文件系统,这个文件系统是image定义的。
dpcker ps
# 删除指定名字的已停止的container
ssh ${worker} 'sudo docker ps -qa --no-trunc -f "status=exited" -f "name=rain-${name}*" |awk "{ print $1 }" | xargs sudo docker rm'
-a :显示所有的容器,包括未运行的。
-f :根据条件过滤显示的内容。
--format :指定返回值的模板文件。
-l :显示最近创建的容器。
-n :列出最近创建的n个容器。
--no-trunc :不截断输出。
-q :静默模式,只显示容器编号。
-s :显示总的文件大小。
命令
下面的 containerid 也可以用 containername 代替
docker build -t webapp:latest ./webapp 生成镜像
docker build 可以接收一个参数,需要特别注意的是,这个参数为一个目录路径 ( 本地路径或 URL 路径 ),而并非 Dockerfile 文件的路径。在 docker build 里,这个我们给出的目录会作为构建的环境目录,我们很多的操作都是基于这个目录进行的。例如,在我们使用 COPY 或是 ADD 拷贝文件到构建的新镜像时,会以这个目录作为基础目录。
在默认情况下,docker build 也会从这个目录下寻找名为 Dockerfile 的文件,将它作为 Dockerfile 内容的来源。如果我们的 Dockerfile 文件路径不在这个目录下,或者有另外的文件名,我们可以通过 -f 选项单独给出 Dockerfile 文件的路径。
docker pull imagenametag 从can
docker info 查看docker引擎信息
docker inspect imageid/containerid 查看镜像或容器信息(可以看到volume等信息,在 Mounts 部分)
docker rmi imageid 删除镜像
docker run --name nginx -d nginx:1.12 后台启动容器,--rm 和 -d 不能同时使用
docker ps 查看正在运行的容器列表
docker ps -a 查看所有容器列表
docker stop containerid 停止容器
docker rm containerid 删除容器
docker exec -it containerid bash 进入正在运行的容器的终端中
docker run -d --name nginx -p 8080:80 -p 443:443 nginx:1.12 将容器的 80 端口映射到宿主操作系统的 8080 端口
docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html nginx:1.12 将宿主环境的 /webapp/html 目录映射到容器中的 /usr/share/nginx/html 目录,定义目录时必须使用绝对路径,host的目录如果写相对路径,就会默认补全父目录( 如/var/lib/docker/volumes/logs/_data ),而且目录不存在的话,会自动创建。
volume
docker logs containerid 显示的是容器内部运行输出到控制台的信息 STDOUT STDERR
docker cp containerid:containerpath hostpath 从容器中复制文件或目录到宿主环境,也可以反过来
数据卷
docker run -d --name webapp -v html:/webapp/html webapp:latest
我们使用 -v 选项挂载数据卷时,如果数据卷不存在(如上面的html卷),Docker 会为我们自动创建和分配宿主操作系统的目录,而如果同名数据卷已经存在,则会直接引用。
挂载文件
除了挂载目录,也可以直接挂载文件,挂载文件时,只是都要写绝对路径。如果文件不存在,就是以这个文件的名字去创建一个文件夹。比如创建一个名字叫 1.js 的文件夹。
docker run -v /Users/liujunyang/work/xuetang/node-auth/lib/config/env/1.js:/1.js testsinglefile
# deploy的实现
run_opts = ['-v', `${name}:/config`, '-v', 'logs:/rain/logs', '-v', '/share/xuetang/nodejs-deploy/common_config:/rain/common_config', '-v', `/share/xuetang/nodejs-deploy/prdoctionlist/${name}/production.js:/rain/lib/config/env/production.js`, '--env', 'NODE_ENV=production', '--env','NODE_PATH=/usr/local/lib/node_modules', '--hostname', hostname, project_conf];
禁用docker attach containerid 将容器中的主程序转为了当前的“前台”运行,通过 Ctrl + C 来向程序发送停止信号,让程序停止 ( 从而容器也会随之停止 )。
Dockerfile
定义文件系统 Dockerfiles describe how to assemble a private filesystem for a container, and can also contain some metadata describing how to run a container based on this image. 就是打包成了一个死的文件系统。实例化就成了container。 所以一般是:定义的文件系统 + 执行build image时所在的机器(即host)
当启动container的时候,会临时在所有layer最上层再加一层container layer
You can think of these Dockerfile commands as a step-by-step recipe on how to build up your image
执行 docker build 时传入在的文件夹就是 build context
# Copy the file from your host to your current location.
# host就是指build image的时候所在的机器
COPY package.json .
# Run the command inside your image filesystem.
# 这种指令就是在打包image的时候就执行了。并不是运行container的时候安装,运行container的时候直接使用image里面打包好的。
RUN npm install
# Inform Docker that the container is listening on the specified port at runtime.
EXPOSE 8080
# Run the specified command within the container.
# 这种指令才是启动container的时候执行的
# The CMD directive is the first example of specifying some metadata in your image that describes how to run a container based on this image
# CMD指令描述了如何运行一个基于这个image的container
CMD [ "npm", "start" ]
查看官方资料
\
在RUN 中,\在行尾时表示续后面一行。是在同一层layer中。
CMD
一个 Dockerfile 中只能有一个 CMD,如果有多个,只有最后一个有效。
别把 CMD 和 RUN 搞混了 Do not confuse RUN with CMD. RUN actually runs a command and commits the result; CMD does not execute anything at build time, but specifies the intended command for the image.
ADD
The ADD instruction copies new files, directories or remote file URLs from and adds them to the filesystem of the image at the path .
COPY指令和ADD指令的唯一区别在于是否支持从远程URL获取资源。COPY指令只能从执行docker build所在的主机上读取资源并复制到镜像中。而ADD指令还支持通过URL从远程服务器读取资源并复制到镜像中。 满足同等功能的情况下,推荐使用COPY指令。ADD指令更擅长读取本地tar文件并解压缩。
ARG
ARG 表示的是 build image 的时候传的命令行参数
WORKDIR
执行 RUN时即使cd到别的目录了, 但是并不会影响下一条命令的当前路径,依然是 WORKDIR
变量
定义:
ARG
ENV
ENV 指令所定义的变量,永远会覆盖 ARG 所定义的变量,即使它们定时的顺序是相反的。
使用:
cd ${DEPLOY_DIR}
echo "$name is good"
构建缓存
由于镜像是多个指令所创建的镜像层组合而得,那么如果我们判断新编译的镜像层与已经存在的镜像层未发生变化,那么我们完全可以直接利用之前构建的结果,而不需要再执行这条构建指令,这就是镜像构建缓存的原理。
基于这个原则,我们在条件允许的前提下,更建议将不容易发生变化的搭建过程放到 Dockerfile 的前部,充分利用构建缓存提高镜像构建的速度。另外,指令的合并也不宜过度,而是将易变和不易变的过程拆分,分别放到不同的指令里。
COPY ["package.json","/tmp/"] 和 RUN cd /tmp && npm install 的时候如果 package.json 文件内容没有变化,是可以击中 docker 缓存的,可以参考 node上线流程 中的介绍。
关于< none > : < none >镜像
docker images -a 会查出来很多< none > : < none >的镜像。如:
REPOSITORY TAG IMAGE ID CREATED SIZE
...
build.ykt.io/rain-pipe 2.9.2 e794868c55d7 38 hours ago 1.066 GB
<none> <none> 18a82dbb1216 38 hours ago 1.066 GB
<none> <none> 9bbccd83f2f4 38 hours ago 905.3 MB
<none> <none> 39a14a3d9bd1 38 hours ago 904.8 MB
<none> <none> 95a60615d2d3 38 hours ago 854.9 MB
...
build.ykt.io/rain-node latest 1133616c22bb
...
以 build.ykt.io/rain-pipe 2.9.2 e794868c55d7 为例,
一层层根据 Parent 查询image依赖的结果如下:
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} e794868c55d7
sha256:18a82dbb1216e6c3b5ece04bc00aa99154078bb0643a6fe9aac6cf42f033d1d0
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 18a82dbb1216e6c3b5ece04bc00aa99154078bb0643a6fe9aac6cf42f033d1d0
sha256:9bbccd83f2f4e956ba42c315da1fb73951df7c6be0ecd84736adf92daf8dc45e
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 9bbccd83f2f4e956ba42c315da1fb73951df7c6be0ecd84736adf92daf8dc45e
sha256:39a14a3d9bd1d949ffdb271eecc068bee572cbe9838f20a4d6c025c4c5111572
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 39a14a3d9bd1d949ffdb271eecc068bee572cbe9838f20a4d6c025c4c5111572
sha256:95a60615d2d38ee751b88544cc916dc11fead043c1833e49e6f3df2b1f8779e2
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 95a60615d2d38ee751b88544cc916dc11fead043c1833e49e6f3df2b1f8779e2
sha256:2e964b2493609737f6915a937e304c2be8c076f6321563cd9baa329003dd27fe
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 2e964b2493609737f6915a937e304c2be8c076f6321563cd9baa329003dd27fe
sha256:b6329b54460a81fff3aa8d22f9cb5a8d5e3626b731d734454eb1b22617715aaa
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} b6329b54460a81fff3aa8d22f9cb5a8d5e3626b731d734454eb1b22617715aaa
sha256:57679fce7e4e610bb37b7042579528c99dda47200889906e79212c7dfc1cdb25
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 57679fce7e4e610bb37b7042579528c99dda47200889906e79212c7dfc1cdb25
sha256:1133616c22bb3023928e20370aa84627b9e6e120ff3e9cc36c8ebd4e3f6ccf9d
[root@buildserver nodejs-deploy]# docker inspect -f {{.Parent}} 1133616c22bb3023928e20370aa84627b9e6e120ff3e9cc36c8ebd4e3f6ccf9d
[root@buildserver nodejs-deploy]#
可以看到最后的依赖 1133616 为 build.ykt.io/rain-node ,已经查不到它的父级 image。
再通过 docker inspect -f {{.ContainerConfig.Cmd}} 57679fce7e4e 等倒过来一层层查看,发现正是 dockerfile 中的一行行的信息。所以初步推测这些< none > : < none >的镜像是在build镜像的过程中的产物,甚至可以从 docker inspect xxx 中看到临时 container 的信息,而且可以看到 RootFS.Layers 数组中的层前面的内容都是一样的,随着 build 往后面不停地 push 新的 layer。
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 1133616c22bb3023928e20370aa84627b9e6e120ff3e9cc36c8ebd4e3f6ccf9d
[/bin/sh -c #(nop) CMD ["node"]]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 57679fce7e4e610bb37b7042579528c99dda47200889906e79212c7dfc1cdb25
[/bin/sh -c #(nop) MAINTAINER mahui@xuetangx.com]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} b6329b54460a81fff3aa8d22f9cb5a8d5e3626b731d734454eb1b22617715aaa
[/bin/sh -c #(nop) ARG name]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 2e964b2493609737f6915a937e304c2be8c076f6321563cd9baa329003dd27fe
[/bin/sh -c #(nop) ENV DEPLOY_DIR=/rain]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 95a60615d2d38ee751b88544cc916dc11fead043c1833e49e6f3df2b1f8779e2
[/bin/sh -c #(nop) COPY multi:c8f17aa6f60af2cf46f08bf64f5bc4a45bf00e6c24b0986ad77a42a50042ae89 in /tmp/]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 39a14a3d9bd1d949ffdb271eecc068bee572cbe9838f20a4d6c025c4c5111572
[|1 name=pipe /bin/sh -c cd /tmp && mv package_nov.json package.json && npm install]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 9bbccd83f2f4e956ba42c315da1fb73951df7c6be0ecd84736adf92daf8dc45e
[/bin/sh -c #(nop) ADD dir:8141f770a89bc5f2dbf8ac5928af9109f91a849c17253e61c8663fa2e64882bf in /rain]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} 18a82dbb1216e6c3b5ece04bc00aa99154078bb0643a6fe9aac6cf42f033d1d0
[|1 name=pipe /bin/sh -c cp -a /usr/local/lib/node_modules ${DEPLOY_DIR}/ && cp -a /tmp/node_modules ${DEPLOY_DIR}/ && cd ${DEPLOY_DIR} && cp deploy/run.sh /run.sh && chmod +rx /run.sh && cp deploy/pm2_${name}.yml ${DEPLOY_DIR} && rm -rf /tmp/node_modules && mkdir /config && echo -e "\033[32m $name\033[0m" && echo "$name" > /project_config && cat /project_config]
[root@buildserver nodejs-deploy]# docker inspect -f {{.ContainerConfig.Cmd}} e794868c55d7
[/bin/sh -c #(nop) CMD ["/run.sh"]]
[root@buildserver nodejs-deploy]#
所以这些 docker images -a 列出来的 < none > : < none >的镜像最好不要删除。