Docker教程09:创建Dockers镜像
dockerfile文件使用
docker build
命令会根据dockerfile文件及上下文构建新Docker镜像.构建上下文是指dockerfile所在的本地路径或一个URL(Git仓库地址).构建上下文环境会被递归处理,所以,构建所指定的路径还包括了子目录,而URL还包括了其中指定的子模块.
构建镜像
将当前目录做为构建上下文时,可以像下面这样使用docker build命令构建镜像:
$ ~/Downloads/hello-system$ sudo docker build .
Sending build context to Docker daemon 70.14kB
说明:构建会在Docker后台守护进程(daemon)中执行,而不是CLI中.构建前,构建进程会将全部内容(递归)发送到守护进程.大多情况下,应该将一个空目录作为构建上下文环境,并将dockerfile文件放在该目录下.
在构建上下文中使用的dockerfile文件,是一个构建指令文件.为了提高构建性能,可以通过.dockerignore文件排除上下文目录下,不需要的文件和目录.
dockerfile一般位于构建上下文的根目录下,也可以通过-f指定该文件的位置:
$ sudo docker build -f /home/keke/Downloads/hello-system/dockerfile .
构建时,还可以通过-t参数指定构建成后,镜像的仓库,标签等:
镜像标签
$ ~/Downloads/hello-system$ sudo docker build -t keke/myapp .
如果存在多个仓库下,或使用多个镜像标签,就可以使用多个-t参数:
$ docker build -t keke/myapp:1.0.2 -t keke/myapp:latest .
在Docker守护进程执行dockerfile中的指令前,首先会对dockerfile进行语法检查,有语法错误时会返回:
$ docker build -t test/myapp .
Sending build context to Docker daemon 2.048 kB
Error response from daemon: Unknown instruction: RUNCMD
dockerfile文件格式
dockerfile文件中指令不区分大小写,但为了更易区分,约定使用大写形式.
Docker 会依次执行dockerfile中的指令,文件中的第一条指令必须是FROM,FROM指令用于指定一个基础镜像.
FROM指令用于指定其后构建新镜像所使用的基础镜像.FROM指令必是dockerfile文件中的首条命令,启动构建流程后,Docker将会基于该镜像构建新镜像,FROM后的命令也会基于这个基础镜像.
dockerfile文件格式如下:
# Comment
INSTRUCTION arguments
dockerfile文件中指令不区分大小写,但为了更易区分,约定使用大写形式.
Docker 会依次执行dockerfile中的指令,文件中的第一条指令必须是FROM,FROM指令用于指定一个基础镜像.
FROM语法格式为:
FROM <image> 或 FROM <image>:<tag>
通过FROM指定的镜像,可以是任何有效的基础镜像.FROM有以下限制:
FROM必须是dockerfile中第一条非注释命令 在一个dockerfile文件中创建多个镜像时,FROM可以多次出现.只需在每个新命令FROM之前,记录提交上次的镜像ID. tag或digest是可选的,如果不使用这两个值时,会使用latest版本的基础镜像
RUN
RUN用于在镜像容器中执行命令,其有以下两种命令执行方式: shell执行 在这种方式会在shell中执行命令,Linux下默认使用/bin/sh -c,Windows下使用cmd /S /C. 注意:通过SHELL命令修改RUN所使用的默认shell
RUN <command>
exec执行
RUN ["executable", "param1", "param2"]
RUN可以执行任何命令,然后在当前镜像上创建一个新层并提交.提交后的结果镜像将会用在dockerfile文件的下一步.
通过RUN执行多条命令时,可以通过\换行执行:
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
也可以在同一行中,通过分号分隔命令:
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
RUN指令创建的中间镜像会被缓存,并会在下次构建中使用.如果不想使用这些缓存镜像,可以在构建时指定–no-cache参数,如:docker build –no-cache.
CMD
CMD用于指定在容器启动时所要执行的命令.CMD有以下三种格式:
CMD ["executable","param1","param2"]
CMD ["param1","param2"]
CMD command param1 param2
CMD不同于RUN,CMD用于指定在容器启动时所要执行的命令,而RUN用于指定镜像构建时所要执行的命令. CMD与RUN在功能实现上也有相似之处.如:
docker run -t -i keke/static /bin/true 等价于:cmd ["/bin/true"]
CMD在dockerfile文件中仅可指定一次,指定多次时,会覆盖前的指令. 另外,docker run命令也会覆盖dockerfile中CMD命令.如果docker run运行容器时,使用了dockerfile中CMD相同的命令,就会覆盖dockerfile中的CMD命令. 如,我们在构建镜像的dockerfile文件中使用了如下指令:
CMD ["/bin/bash"]
使用docker build构建一个新镜像,镜像名为keke/test.构建完成后,使用这个镜像运行一个新容器,运行效果如下:
sudo docker run -i -t keke/test
在使用docker run运行容器时,我们并没有在命令结尾指定会在容器中执行的命令,这时Docker就会执行在dockerfile的CMD中指定的命令. 如果不想使用CMD中指定的命令,就可以在docker run命令的结尾指定所要运行的命令:
sudo docker run -i -t keke/test /bin/ps
这时,docker run结尾指定的/bin/ps命令覆盖了dockerfile的CMD中指定的命令.
ENTRYPOINT
ENTRYPOINT用于给容器配置一个可执行程序.也就是说,每次使用镜像创建容器时,通过ENTRYPOINT指定的程序都会被设置为默认程序.ENTRYPOINT有以下两种形式:
ENTRYPOINT ["executable", "param1", "param2"]
ENTRYPOINT command param1 param2
ENTRYPOINT与CMD非常类似,不同的是通过docker run执行的命令不会覆盖ENTRYPOINT,而docker run命令中指定的任何参数,都会被当做参数再次传递给ENTRYPOINT.dockerfile中只允许有一个ENTRYPOINT命令,多指定时会覆盖前面的设置,而只执行最后的ENTRYPOINT指令.
docker run运行容器时指定的参数都会被传递给ENTRYPOINT,且会覆盖CMD命令指定的参数.如,执行docker run
ENTRYPOINT ["/usr/bin/nginx"]
完整构建代码:
FROM ...
MAINTAINER keke "2536495681@gmail.com"
RUN ...
# 指定容器内的程序将会使用容器的指定端口
# 配合 docker run -p
EXPOSE ...
使用docker build构建镜像,并将镜像指定为keke/test:
sudo docker build -t="itbilu/test" .
构建完成后,使用keke/test启动一个容器:
sudo docker run -i -t keke/test -g "daemon off;"
在运行容器时,我们使用了-g “daemon off;” ,这个参数将会被传递给ENTRYPOINT,最终在容器中执行的命令为/usr/sbin/nginx -g “daemon off;” .
EXPOSE
EXPOSE用于指定容器在运行时监听的端口:
EXPOSE <port> [<port>...]
EXPOSE并不会让容器的端口访问到主机.要使其可访问,需要在docker run运行容器时通过-p来发布这些端口,或通过-P参数来发布EXPOSE导出的所有端口.
- RUN: 指定镜像被构建时要运行的命令
- CMD: 指定容器被启动时要运行的命令
- ENTRYPOINT: 同 CMD ,但不会被 docker run -t 覆盖
- WORKDIR: CMD/ENTRYPOINT 会在这个目录下执行
- VOLUME:创建挂载点,即向基于所构建镜像创始的容器添加卷
- ADD:用于复制构建环境中的文件或目录到镜像中
- COPY:同样用于复制构建环境中的文件或目录到镜像中
docker history images-name
从新镜像启动容器
docker run -d -p 4000:80 --name [name] #可以在 Dokcer 宿主机上指定一个具体的端口映射到容器的80端口上
守护容器
docker run -d container-name #创建守护容器
docker top container-name #查看容器内进程
docker exec container-name touch a.txt #在容器内部运行进程
docker stop container-name #停止容器
学习资源
- Docker中文网站:http://www.docker.org.cn
- Docker中文文档:http://www.dockerinfo.net/document
- Docker安装手册:http://www.docker.org.cn/book/install.html
- 一小时Docker教程 :https://blog.csphere.cn/archives/22
- Docker中文指南:http://www.widuu.com/chinese_docker/index.html