前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dockerfile、Docker-Compose基本命令与介绍

Dockerfile、Docker-Compose基本命令与介绍

作者头像
唐成勇
发布2019-05-26 10:57:06
1.7K0
发布2019-05-26 10:57:06
举报
文章被收录于专栏:唐成勇唐成勇唐成勇

一、Dockerfile基本命名

指令

说明

备注

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 "executable", "param1", "param2"

每条RUN指令将在当前镜像基础上执行指定命令,并提交为新的镜像,后续的RUN都在之前RUN提交后的镜像为基础,镜像是分层的,可以通过一个镜像的任何一个历史提交点来创建,类似源码的 版本控制 。

exec 方式会被解析为一个 JSON 数组,所以必须使用双引号而不是单引号。exec 方式不会调用一个命令 shell,所以也就不会继承相应的变量,如:

RUN [ "echo", "$HOME" ]

这种方式是不会达到输出 HOME 变量的,正确的方式应该是这样的

RUN [ "sh", "-c", "echo", "$HOME" ]

RUN产生的缓存在下一次构建的时候是不会失效的,会被重用,可以使用--no-cache选项,即docker build --no-cache,如此便不会缓存。 注意:apt-get updateapt-get install 被放在一个 RUN 指令中执行,这样能够保证每次安装的是最新的包。如果 apt-get install 在单独的 RUN 中执行,则会使用 apt-get update 创建的镜像层,而这一层可能是很久以前缓存的。

CMD有三种使用方式:
CMD  "executable","param1","param2"
CMD  "param1","param2"
CMD command param1 param2 (shell form)

CMD指定在 Dockerfile 中只能使用一次,如果有多个,则只有最后一个会生效。

CMD的目的是为了在启动容器时提供一个默认的命令执行选项。如果用户启动容器时指定了运行的命令,则会覆盖掉CMD指定的命令。

CMD会在启动容器的时候执行,build 时不执行,而RUN只是在构建镜像的时候执行,后续镜像构建完成之后,启动容器就与RUN无关了,这个初学者容易弄混这个概念,这里简单注解一下。

Docker学习笔记:Dockerfile

二、Dockerfile 基本结构

一般的,Dockerfile 分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。’#’ 为 Dockerfile 中的注释。先看下面一个小例子:

# 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"]

三、构建镜像

3.1 编写Dockerfile文件

vim Dockerfile

FROM alpine:latest
MAINTAINER troy
CMD echo "Hello Workd!"

3.2 构建镜像

docker build -t hello_world .

3.3 运行镜像

docker run hello_world
clipboard.png
clipboard.png

记:

1.表示当前用户使用的shell是/bin/bash,所谓的shell你可以理解为操作系统和人之间交互的平台。例如windows系统的桌面环境就是一个shell。 bin目录中基本上都是可执行的命令。

启动容器并启动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容器也就退出了。

Shell 和 Exec 格式

我们可用两种方式指定 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-compose 是用来做docker 的多容器控制,是一个用来把 docker 自动化的东西。有了 docker-compose 你可以把所有繁复的 docker 操作全都一条命令,自动化的完成。

4.1 常用命令

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容器

4.2 docker-compose.yml

depends_on

在使用 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 两个服务,因为在配置文件中定义了依赖关系。

links

还记得上面的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

相应的环境变量也将被创建。

volumes

挂载一个目录或者一个已存在的数据卷容器,可以直接使用 [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

volumes_from

从其它容器或者服务挂载数据卷,可选的参数是 :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 格式

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Dockerfile基本命名
  • 二、Dockerfile 基本结构
  • 三、构建镜像
    • 3.1 编写Dockerfile文件
      • 3.2 构建镜像
        • 3.3 运行镜像
        • 记:
        • 四、Docker-Compose
          • 4.1 常用命令
            • 4.2 docker-compose.yml
              • depends_on
              • links
              • volumes
              • volumes_from
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档