使用 Dockerfile 构建镜像

进入我的博客,了解更多!

关于 Dockerfile

在构建镜像时,可以选择使用 Dockerfile 来构建。Docker 会读取 Dockerfile 中的指令自动构建镜像。所有命令行中可以使用的 Docker 命令都能在 Dockerfile 中使用。

docker build path 命令会在 path 目录下找到 Dockerfile,然后执行 Dockerfile 中的指令;docker 会先将当前环境发送到 Docker daemon(Docker 守护进程),注意这里的当前环境指的是path目录,.代表当前目录。

大多数情况下,path 最好是一个干净的文件夹,只包含 Dockerfile 以及其他构建所必需的文件。

# 在当前目录下,通过 Dockerfile 文件构建
➜ docker build .
Sending build context to Docker daemon  6.51 MB

# DockerFile 也可以不在当前目录下,通过 -f 进行指定
➜ docker build -f /path/to/a/Dockerfile .

基本编写规则

  • Dockerfile 指令不区分大小写,但是为了更容易区分命令与参数,通常将命令大写

    # Comment
    INSTRUCTION arguments
    
  • FROM 指令会初始化构建环境并设置基础镜像,后续的指令都将在这个环境下得到执行。正因为如此,Dockerfile 必须以 FROM 指令开头,唯一的例外是 ARG 指令。

    # 格式:
    # FROM <image> [AS <name>]
    # FROM <image>[:<tag>] [AS <name>]
    # FROM <image>[@<digest>] [AS <name>]
    
    # 指定 centos 为构建的基础镜像,默认获取最新的(latest)镜像
    FROM centos
    
    # 等同于 FROM centos
    FROM centos:latest
    
    # 指定版本标签
    FROM centos:5
    
  • RUN 指令会在当前镜像上执行指定命令,并且将结果提交至一个新的镜像,供 Dockerfile 中指定下一步继续使用。

    # 格式:
    # RUN <command>
    # RUN ["executable", "param1", "param2"]
    
    RUN mkdir /data
    
  • CMD 指令,一个 Dockerfile 中只能存在一个 CMD 指令,如果存在多个的话,只有最后一个 CMD 指令会生效。
    CMD 的主要目的在于为容器启动后提供默认值的可执行命令或参数,也可以省略命令,不过在这种情况下需要指定 ENTRYPOINT 指令。

    # 格式:
    # CMD ["executable","param1","param2"] (exec form, this is the preferred form)
    # CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
    # CMD command param1 param2 (shell form)
    
    # CMD通过 /bin/sh -c 执行
    FROM ubuntu
    CMD echo "This is a test." | wc -
    
    # 通过 /usr/bin/wc 执行
    FROM ubuntu
    CMD ["/usr/bin/wc","--help"]
    
  • ENTRYPOINT 指令指定容器启动时执行的命令及参数。可以在使用 docker run 启动容器时通过加上 --entrypoint 对其进行覆盖。

    # 格式:
    # ENTRYPOINT ["executable", "param1", "param2"] (exec form, preferred)
    # ENTRYPOINT command param1 param2 (shell form)
    
    FROM ubuntu
    ENTRYPOINT ["top", "-b"]
    CMD ["-c"]
    
  • EXPOSE 命令的作用是通知容器运行期间监听指定的网络端口,同时也可以指定传输协议,默认为 TCP。

    # 格式:
    # EXPOSE <port> [<port>/<protocol>...]
    
    # protocol 不是 tcp 时,需要显示指定
    EXPOSE 80/udp
    
    # 同时指定tcp/udp
    EXPOSE 80/tcp
    EXPOSE 80/udp
    

    如果要覆盖 EXPOSE,可以在运行时通过 -p 指定

    docker run -p 80:80/tcp -p 80:80/udp
    
  • ADD 命令将指定路径的文件或文件夹复制到镜像内指定路径下。

    # ADD [--chown=<user>:<group>] <src>... <dest>
    # ADD [--chown=<user>:<group>] [<src>,... <dest>]
    # 添加文件到 `WORKDIR`/relativeDir/
    ADD test relativeDir/
    
    # 添加文件到 /absoluteDir/
    ADD test /absoluteDir/
    

注意:src 路径必须在构建镜像时指定的环境(路径)内部

案例

基于 centos 搭建 tomcat 环境

  1. 创建 Dockerfile 文件,完整内容如下:

    FROM centos:7
    
    ENV CATALINA_HOME /usr/local/tomcat
    ENV PATH $CATALINA_HOME/bin:$PATH
    WORKDIR $CATALINA_HOME
    
    RUN yum install -y java-1.8.0-openjdk \
      && yum install -y wget \
      && wget http://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.14/bin/apache-tomcat-9.0.14.tar.gz \
      && mkdir -p "$CATALINA_HOME" \
      && tar -xzf apache-tomcat-9.0.14.tar.gz -C /usr/local/tomcat --strip-components=1 \
      && rm -r apache-tomcat-9.0.14.tar.gz \
      && yum clean all
    
    EXPOSE 80/tcp
    
    CMD ["catalina.sh", "run"]
    

    说明:

    • 当我们在终端上执行 yum install 命令时,会提示是否确认安装。但是我们在使用 Dockerfile 时,不会有类似的输入确认环节,所以我们可以通过在命令中指定 -y 自动确认以跳过该环节,否则将导致构建失败。
      # yum install wget
      # ...
      # Total download size: 38 M
      # Installed size: 122 M
      # Is this ok [y/d/N]:_
      
      ➜ yum install -y wget
      
    • 清理缓存和垃圾文件,避免镜像过于臃肿。
      ➜ rm -r apache-tomcat-9.0.14.tar.gz
      ➜ yum clean all
      
  2. Dockerfile 文件所在目录执行 docker build -t web:v1 .,其中 web 为镜像名称,v1 为版本号,. 指当前目录。

    ➜ docker build -t web:v1 .
    Sending build context to Docker daemon  2.048kB
    ...
    ...
    Successfully built 1354c6469ae9
    Successfully tagged web:v1
    
    ➜ docker images
    REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
    web                 v1                  6875af3e6d82        38 seconds ago      390MB
    centos              7                   1e1148e4cc2c        3 weeks ago         202MB
    
  3. 验证镜像是否构建成功,执行以下命令后访问:http://localhost:8000/

    ➜ docker run -dit -p 8000:8080 web:v1
    

参考链接

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容