指令 | 说明 | 备注 |
---|---|---|
FROM | 指定所建立镜像的基础镜像 | 第一条指令必须为 FROM 指令。格式为 FROM <image> 或FROM <image>:<tag> 。 |
MAINTAINER | 指定维护者信息 | 格式为 MAINTAINER <name> |
RUN | RUN 指令一般用于安装应用和软件包。 | 在镜像中要执行的命令,格式为 RUN <command> 或 RUN ["executable", "param1", "param2"] 。前者默认将在 shell 终端中运行命令,即 /bin/bash -c ;后者则使用 exec 执行。指定使用其它终端能够经过第二种方式实现,例如 RUN [“/bin/bash”, “-c”,”echo hello”] 。每条RUN指令将在当前镜像的基础上执行指定命令,并提交为新的镜像。当命令较长时可使用换行。例如:RUN apt-get update \&& apt-get install -ylibsnappy-dev zliblg-dev libbz2-dev \&& rm -rf /var/cache/apt |
CMD | 指定启动容器时默认执行的命令 | 支持三种格式:1. CMD["executable","param1","param2"] 使用 exec 执行,推荐方式;2. CMD command param1 param2 在 /bin/bash 中执行,提供给须要交互的应用;3. CMD ["param1","param2"] 提供给 ENTRYPOINT 的默认参数; |
LABEL | 指定生成镜像的元数据标签信息 | |
EXPOSE | 声明镜像内服务所监听的端口 | 指定容器要打开的端口 |
ENV | 指定环境变量 | 格式为 ENV <key> <value> 。 指定一个环境变量,会被后续 RUN 指令使用,并在容器运行时保持。 |
ADD | 赋值指定的路径下的内容到容器中的路径下,能够为URL;若是为tar文件,会自动解压到路径下 | 至关于 COPY ,可是比 COPY 功能更强大 |
COPY | 赋值本地主机的路径下的内容到容器中的路径下;通常状况下推荐使用COPY 而不是ADD |
复制本地主机的 (为 Dockerfile 所在目录的相对路径)到容器中的。用法同ADD,惟一的不一样是不能指定远程文件 URLS。 |
VOLUME | 建立数据挂载点 | 挂载目录,格式为VOLUME ["/data"] |
USER | 指定运行容器时的用户名或UID | |
WORKDIR | 配置工做目录 | 指定当前工做目录,至关于 cd |
ARG | 指定镜像内使用的参数(例如版本号信息等) | |
ONBUILD | 配置当前所建立的镜像做为其余镜像的基础镜像时,所执行的建立操做的命令 | |
STOPSIGNAL | 容器退出的信号 | |
HEALTHCHECK | 如何进行健康检查 | |
CMD、ENTRYPOINT | 容器启动时执行指令 | 配置容器启动后执行的命令,而且不可被 docker run 提供的参数覆盖,而CMD是能够被覆盖的。若是须要覆盖,则可使用docker run --entrypoint 选项。每一个 Dockerfile 中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效。 |
每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,后续的RUN都在以前RUN提交后的镜像为基础,镜像是分层的,能够经过一个镜像的任何一个历史提交点来建立,相似源码的 版本控制 。php
exec 方式会被解析为一个 JSON 数组,因此必须使用双引号而不是单引号。exec 方式不会调用一个命令 shell,因此也就不会继承相应的变量,如:html
RUN [ "echo", "$HOME" ]
这种方式是不会达到输出 HOME 变量的,正确的方式应该是这样的python
RUN [ "sh", "-c", "echo", "$HOME" ]
RUN产生的缓存在下一次构建的时候是不会失效的,会被重用,可使用--no-cache选项,即docker build --no-cache
,如此便不会缓存。
注意:apt-get update
和 apt-get install
被放在一个 RUN 指令中执行,这样可以保证每次安装的是最新的包。若是 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 建立的镜像层,而这一层多是好久之前缓存的。mysql
CMD "executable","param1","param2" CMD "param1","param2" CMD command param1 param2 (shell form)
CMD指定在 Dockerfile 中只能使用一次,若是有多个,则只有最后一个会生效。nginx
CMD的目的是为了在启动容器时提供一个默认的命令执行选项。若是用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。c++
CMD会在启动容器的时候执行,build 时不执行,而RUN只是在构建镜像的时候执行,后续镜像构建完成以后,启动容器就与RUN无关了,这个初学者容易弄混这个概念,这里简单注解一下。
通常的,Dockerfile
分为四部分:基础镜像信息、维护者信息、镜像操做指令和容器启动时执行指令。’#’ 为 Dockerfile 中的注释。先看下面一个小例子:redis
# This my first nginx Dockerfile # Version 1.0 # Base images 基础镜像 FROM centos #MAINTAINER 维护者信息 MAINTAINER tianfeiyu #ENV 设置环境变量 ENV PATH /usr/local/nginx/sbin:$PATH #ADD 文件放在当前目录下,拷过去会自动解压 ADD nginx-1.8.0.tar.gz /usr/local/ ADD epel-release-latest-7.noarch.rpm /usr/local/ #RUN 执行如下命令 RUN rpm -ivh /usr/local/epel-release-latest-7.noarch.rpm RUN yum install -y wget lftp gcc gcc-c++ make openssl-devel pcre-devel pcre && yum clean all RUN useradd -s /sbin/nologin -M www #WORKDIR 至关于cd WORKDIR /usr/local/nginx-1.8.0 RUN ./configure --prefix=/usr/local/nginx --user=www --group=www --with-http_ssl_module --with-pcre && make && make install RUN echo "daemon off;" >> /etc/nginx.conf #EXPOSE 映射端口 EXPOSE 80 #CMD 运行如下命令 CMD ["nginx"]
vim Dockerfilesql
FROM alpine:latest MAINTAINER troy CMD echo "Hello Workd!"
docker build -t hello_world .
docker run hello_world
1.表示当前用户使用的shell是/bin/bash,所谓的shell你能够理解为操做系统和人之间交互的平台。例如windows系统的桌面环境就是一个shell。
bin目录中基本上都是可执行的命令。docker
启动容器并启动bash(交互方式
):
$docker run -i -t <image_name/continar_id> /bin/bash
2.保存对容器的修改(commit) 当你对某一个容器作了修改以后(经过在容器中运行某一个命令),能够把对容器的修改保存下来,这样下次能够从保存后的最新状态运行该容器。
$docker commit ID new_image_name
固然若是在保存成新镜像的时候想添加新的 dockerfile命令,好比,启动进入新的目录。
docker commit -c "WORKDIR /usr/bin" 07c5f9ed32b0 test-images
固然你也能够在旧镜像的基础上写一个新的dockerfile,用dockerfile生成新的镜像。
Note: image至关于类,container至关于实例,不过能够动态给实例安装新软件,而后把这个container用commit命令固化成一个image。
Dockerfile文件的每条指令生成镜像的一层(注:一个镜像不能超过127层
)。Dockerfile中的指令被一条条地执行。每一步都建立一个新的容器,在容器中执行指令并提交修改。当全部指令执行完毕后,返回最终的镜像id。
前台运行:
CMD 指令就是用于指定默认的容器主进程的启动命令的。提到 CMD 就不得不提容器中应用在前台执行和后台执行的问题。这是初学者常出现的一个混淆。
Docker 不是虚拟机,容器中的应用都应该之前台执行,而不是像虚拟机、物理机里面那样,用 upstart/systemd 去启动后台服务,容器内没有后台服务的概念。
一些初学者将 CMD 写为:
CMD service nginx start
而后发现容器执行后就当即退出了。甚至在容器内去使用 systemctl 命令结果却发现根本执行不了。这就是由于没有搞明白前台、后台的概念,没有区分容器和虚拟机的差别,依旧在以传统虚拟机的角度去理解容器。
对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它须要关心的东西。
而使用 service nginx start 命令,则是但愿 upstart 来之后台守护进程形式启动 nginx 服务。而刚才说了 CMD service nginx start 会被理解为
CMD [ "sh", "-c", "service nginx start"],
所以主进程其实是 sh。那么当 service nginx start 命令结束后,sh 也就结束了,sh 做为主进程退出了,天然就会令容器退出。
正确的作法是直接执行 nginx 可执行文件,而且要求之前台形式运行。好比:
CMD ["nginx", "-g", "daemon off;"] ENTRYPOINT [ "/usr/sbin/nginx", "-g", "daemon off;" ]
为何要这么作呢?由于Docker容器仅在它的1号进程(PID为1)运行时,会保持运行。若是1号进程退出了,Docker容器也就退出了。
咱们可用两种方式指定 RUN、CMD 和 ENTRYPOINT 要运行的命令:Shell 格式和 Exec 格式,两者在使用上有细微的区别。
Shell 格式
<instruction> <command>
例如:
RUN apt-get install python3 CMD echo "Hello world" ENTRYPOINT echo "Hello world"
当指令执行时,shell 格式底层会调用 /bin/sh -c <command> 。
例以下面的 Dockerfile 片断:
ENV name Cloud Man ENTRYPOINT echo "Hello, $name"
执行 docker run <image> 将输出:
Hello, Cloud Man
注意环境变量 name 已经被值 Cloud Man 替换。
下面来看 Exec 格式。
Exec 格式
<instruction> ["executable", "param1", "param2", ...]
例如:
RUN ["apt-get", "install", "python3"] CMD ["/bin/echo", "Hello world"] ENTRYPOINT ["/bin/echo", "Hello world"]
当指令执行时,会直接调用 <command>,不会被 shell 解析。
例以下面的 Dockerfile 片断:
ENV name Cloud Man ENTRYPOINT ["/bin/echo", "Hello, $name"]
运行容器将输出:
Hello, $name
注意环境变量“name”没有被替换。
若是但愿使用环境变量,照以下修改
ENV name Cloud Man ENTRYPOINT ["/bin/sh", "-c", "echo Hello, $name"]
运行容器将输出:
Hello, Cloud Man
CMD 和 ENTRYPOINT 推荐使用 Exec 格式,由于指令可读性更强,更容易理解。RUN 则两种格式均可以。
一句话:docker-compose 是用来作docker 的多容器控制,是一个用来把 docker 自动化的东西。有了 docker-compose 你能够把全部繁复的 docker 操做全都一条命令,自动化的完成。
docker-compose up -d nginx 构建建启动nignx容器 docker-compose exec nginx bash 登陆到nginx容器中 docker-compose down 删除全部nginx容器,镜像 docker-compose ps 显示全部容器 docker-compose restart nginx 从新启动nginx容器 docker-compose run --no-deps --rm php-fpm php -v 在php-fpm中不启动关联容器,并容器执行php -v 执行完成后删除容器 docker-compose build nginx 构建镜像 。 docker-compose build --no-cache nginx 不带缓存的构建。 docker-compose logs nginx 查看nginx的日志 docker-compose logs -f nginx 查看nginx的实时日志 docker-compose config -q 验证(docker-compose.yml)文件配置,当配置正确时,不输出任何内容,当文件配置错误,输出错误信息。 docker-compose events --json nginx 以json的形式输出nginx的docker日志 docker-compose pause nginx 暂停nignx容器 docker-compose unpause nginx 恢复ningx容器 docker-compose rm nginx 删除容器(删除前必须关闭容器) docker-compose stop nginx 中止nignx容器 docker-compose start nginx 启动nignx容器
在使用 Compose 时,最大的好处就是少打启动命令,可是通常项目容器启动的顺序是有要求的,若是直接从上到下启动容器,必然会由于容器依赖问题而启动失败。
例如在没启动数据库容器的时候启动了应用容器,这时候应用容器会由于找不到数据库而退出,为了不这种状况咱们须要加入一个标签,就是 depends_on,这个标签解决了容器的依赖、启动前后的问题。
例以下面容器会先启动 redis 和 db 两个服务,最后才启动 web 服务:
version: '2' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
注意的是,默认状况下使用 docker-compose up web 这样的方式启动 web 服务时,也会启动 redis 和 db 两个服务,由于在配置文件中定义了依赖关系。
还记得上面的depends_on吧,那个标签解决的是启动顺序问题,这个标签解决的是容器链接问题,与Docker client的--link同样效果,会链接到其它服务中的容器。
格式以下:
links: - db - db:database - redis
使用的别名将会自动在服务容器中的/etc/hosts里建立。例如:
172.12.2.186 db 172.12.2.186 database 172.12.2.187 redis
相应的环境变量也将被建立。
挂载一个目录或者一个已存在的数据卷容器,能够直接使用 [HOST:CONTAINER] 这样的格式,或者使用 [HOST:CONTAINER:ro] 这样的格式,后者对于容器来讲,数据卷是只读的,这样能够有效保护宿主机的文件系统。
Compose的数据卷指定路径能够是相对路径,使用 . 或者 .. 来指定相对目录。
数据卷的格式能够是下面多种形式:
volumes: // 只是指定一个路径,Docker 会自动在建立一个数据卷(这个路径是容器内部的)。 - /var/lib/mysql // 使用绝对路径挂载数据卷 - /opt/data:/var/lib/mysql // 以 Compose 配置文件为中心的相对路径做为数据卷挂载到容器。 - ./cache:/tmp/cache // 使用用户的相对路径(~/ 表示的目录是 /home/<用户目录>/ 或者 /root/)。 - ~/configs:/etc/configs/:ro // 已经存在的命名的数据卷。 - datavolume:/var/lib/mysql
若是你不使用宿主机的路径,你能够指定一个volume_driver。
volume_driver: mydriver
从其它容器或者服务挂载数据卷,可选的参数是 :ro或者 :rw,前者表示容器只读,后者表示容器对数据卷是可读可写的。默认状况下是可读可写的。
volumes_from: - service_name - service_name:ro - container:container_name - container:container_name:rw
参考文档:1. docker与dockerfile教程
2. Docker系列教程22-docker-compose.yml经常使用命令
3. Shell 和 Exec 格式