• 【Docker】Dockerfile常用指令


    参考官方文档:https://docs.docker.com/engine/reference/builder/

    Dockerfile常用指令

    指令说明
    from基础镜像,当前镜像基于(依赖)哪个镜像
    maintainer镜像的维护者和邮箱
    run镜像构建时需要执行的命令
    workdir镜像的工作目录
    expose对外暴露的端口
    env设置环境变量
    add将宿主机的文件复制到镜像中,并自动解压
    copy将宿主机的文件复制到镜像中
    volume容器数据卷,用于数据的保存和持久化
    cmd运行命令,多条CMD只会执行最后一条,参数会被RUN的参数覆盖
    entrypoint运行命令,会把RUN的参数追加到后面
    volume容器数据卷,用于数据的保存和持久化
    cmd运行命令,多条CMD只会执行最后一条,参数会被RUN的参数覆盖
    entrypoint运行命令,会把RUN的参数追加到后面

    在这里插入图片描述

    Dockerfile指令的使用

    FROM

    FROM [--platform=<platform>] <image> [AS <name>]
    
    FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
    
    FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    FROM指令初始化了一个新的构建阶段,并指定了这个构建阶段的基础镜像,每一个Dockerfile都要以FROM指令开始。

    例如:

    FROM centos:7
    
    • 1

    MAINTAINER

    MAINTAINER用来指定Dockerfile的作者,官方已不推荐使用,推荐使用LABEL

    maintainer morris131<morris131@163.com>
    
    • 1

    LABEL

    LABEL <key>=<value> <key>=<value> <key>=<value> ...
    
    • 1

    LABEL用来为镜像添加元数据,是一个key-value结构。

    例如:

    LABEL "com.example.vendor"="ACME Incorporated"
    LABEL com.example.label-with-value="foo"
    LABEL version="1.0"
    LABEL description="This text illustrates \
    that label-values can span multiple lines."
    
    • 1
    • 2
    • 3
    • 4
    • 5

    一个镜像可以指定多个label,可以指定在一行指定多个label。

    LABEL multi.label1="value1" multi.label2="value2" other="value3"
    LABEL multi.label1="value1" \
          multi.label2="value2" \
          other="value3"
    
    • 1
    • 2
    • 3
    • 4

    父镜像的label会被继承。

    可以使用docker image inspect来查看镜像的label。

    $ docker image inspect --format='{{json .Config.Labels}}' centos:7
    {"org.label-schema.build-date":"20201113","org.label-schema.license":"GPLv2","org.label-schema.name":"CentOS Base Image","org.label-schema.schema-version":"1.0","org.label-schema.vendor":"CentOS","org.opencontainers.image.created":"2020-11-13 00:00:00+00:00","org.opencontainers.image.licenses":"GPL-2.0-only","org.opencontainers.image.title":"CentOS Base Image","org.opencontainers.image.vendor":"CentOS"}
    
    • 1
    • 2

    RUN

    RUN <command>
    
    RUN ["executable", "param1", "param2"]
    
    • 1
    • 2
    • 3

    RUN主要用于在镜像里执行指令,比如安装软件,下载文件等。在Linux下默认的shell是/bin/sh -c,在windows下默认的shell是cmd /S /C

    例如:

    run yum install -y wget gcc gcc-c++ automake autoconf libtool make
    
    run wget https://download.redis.io/releases/redis-6.2.5.tar.gz
    
    run tar xzf redis-6.2.5.tar.gz && cd redis-6.2.5 && make
    
    • 1
    • 2
    • 3
    • 4
    • 5

    WORKDIR

    WORKDIR /path/to/workdir
    
    • 1

    WORKDIR指定运行RUN, CMD, ENTRYPOINT, COPYADD等指令的工作目录。

    WORKDIR可以使用多次,如果指定的是一个相对路径,那么会自动拼接上前面的WORKDIR指令指定的路径。

    WORKDIR /a
    WORKDIR b
    WORKDIR c
    
    • 1
    • 2
    • 3

    最终的工作路径将变为/a/b/c

    COPY

    COPY [--chown=<user>:<group>] [--chmod=<perms>] <src>... <dest>
    COPY [--chown=<user>:<group>] [--chmod=<perms>] ["",... ""]
    
    • 1
    • 2

    COPY指令可以把本地的文件复制到镜像里,如果目标目录不存在,则会自动创建。

    例如:

    COPY /foo /bar
    COPY hom* /mydir/
    COPY hom?.txt /mydir/
    COPY test.txt relativeDir/
    
    • 1
    • 2
    • 3
    • 4

    ADD

    ADD [--chown=<user>:<group>] [--chmod=<perms>] [--checksum=<checksum>] <src>... <dest>
    ADD [--chown=<user>:<group>] [--chmod=<perms>] ["",... ""]
    
    • 1
    • 2

    ADDCOPY的功能类似,唯一的区别在于如果复制的是一个gzip等压缩文件时,ADD会帮助我们自动去解压缩文件。

    因此在COPYADD指令中选择的时候,可以遵循这样的原则,所有的文件复制均使用COPY指令,仅在需要自动解压缩的场合使用ADD

    如果要在容器内部复制文件,可以使用run copy xx oo

    ARG

    ARG <name>[=<default value>]
    
    • 1

    ARG用于定义一个变量,可以在Dockerfile中使用,可以在构建时指定构建参数来覆盖这个变量的值。

    FROM busybox
    ARG username
    USER $username
    
    • 1
    • 2
    • 3

    在构建时修改这个变量:

    $ docker build --build-arg username=what_user .
    
    • 1

    ENV

    ENV <key>=<value> ...
    
    • 1

    ENV设置的变量不仅可可以在镜像的构建阶段使用,还会出现在容器中的环境变量里。

    例如:

    ENV MY_NAME="John Doe"
    ENV MY_DOG=Rex\ The\ Dog
    ENV MY_CAT=fluffy
    
    • 1
    • 2
    • 3

    ENV设置的变量可以通过docker image inspect命令来查看:

    $ docker image inspect --format='{{json .Config.Env}}' openjdk:8-jre-alpine
    ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/jvm/java-1.8-openjdk/jre/bin:/usr/lib/jvm/java-1.8-openjdk/bin","LANG=C.UTF-8","JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk/jre","JAVA_VERSION=8u212","JAVA_ALPINE_VERSION=8.212.04-r0"]
    
    • 1
    • 2

    可以在运行时使用run --env =来改变环境变量的值。

    CMD

    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)
    
    • 1
    • 2
    • 3

    CMD可以用来设置容器启动时默认会执行的命令。

    如果docker container run启动容器时指定了其它命令,则CMD命令会被忽略。

    如果定义了多个CMD,只有最后一个会被执行。

    例如:

    CMD echo "This is a test." | wc -
    
    CMD ["/usr/bin/wc","--help"]
    
    • 1
    • 2
    • 3

    默认进入到shell是因为在ubuntu的基础镜像里有定义CMD

    $ docker container run -it centos:7
    [root@ea4a8eb97765 /]# exit
    exit
    
    $ docker history centos:7
    IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
    eeb6ee3f44bd   24 months ago   /bin/sh -c #(nop)  CMD ["/bin/bash"]            0B
    <missing>      24 months ago   /bin/sh -c #(nop)  LABEL org.label-schema.sc…   0B
    <missing>      24 months ago   /bin/sh -c #(nop) ADD file:b3ebbe8bd304723d4…   204MB
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    ENTRYPOINT

    ENTRYPOINT ["executable", "param1", "param2"]
    
    ENTRYPOINT command param1 param2
    
    • 1
    • 2
    • 3

    ENTRYPOINT也可以设置容器启动时要执行的命令,但是和CMD是有区别的。

    CMD设置的命令,可以在docker container run时传入其它命令,覆盖掉CMD的命令,但是ENTRYPOINT所设置的命令是一定会被执行的。

    ENTRYPOINTCMD可以联合使用,ENTRYPOINT设置执行的命令,CMD传递参数。

    CMD测试

    cmd.Dockerfile

    FROM centos:7
    CMD ["echo", "hello cmd"]
    
    • 1
    • 2

    把上面的Dockerfile构建成一个叫cmd的镜象:

    $ docker build -f cmd.Dockerfile -t cmd .
    Sending build context to Docker daemon  327.2MB
    Step 1/2 : FROM centos:7
     ---> eeb6ee3f44bd
    Step 2/2 : CMD ["echo", "hello cmd"]
     ---> Running in 4bddfcb6153c
    Removing intermediate container 4bddfcb6153c
     ---> c92160d2a1d6
    Successfully built c92160d2a1d6
    Successfully tagged cmd:latest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行容器时如果不指定运行时的命令,则会默认执行CMD所定义的命令,打印出hello cmd

    $ docker run --rm -it cmd
    hello cmd
    
    • 1
    • 2

    如果运行容器的时候指定命令,则该命令会覆盖掉CMD的命令,如:

    $ docker run --rm -it cmd echo hello docker
    hello docker
    
    • 1
    • 2

    ENTRYPOINT测试

    entrypoint.Dockerfile

    FROM centos:7
    ENTRYPOINT ["echo", "hello entrypoint"]
    
    • 1
    • 2

    把上面的Dockerfile构建成一个叫entrypoint的镜象:

    $ docker build -f entrypoint.Dockerfile -t entrypoint .
    Sending build context to Docker daemon  327.2MB
    Step 1/2 : FROM centos:7
     ---> eeb6ee3f44bd
    Step 2/2 : ENTRYPOINT ["echo", "hello entrypoint"]
     ---> Running in b74fa51c63a8
    Removing intermediate container b74fa51c63a8
     ---> b3f6c3c624e0
    Successfully built b3f6c3c624e0
    Successfully tagged entrypoint:latest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    运行容器时如果不指定运行时的命令,则会默认执行ENTRYPOINT所定义的命令,打印出hello entrypoint

    $ docker run --rm -it entrypoint
    hello entrypoint
    
    • 1
    • 2

    但是容器里ENTRYPOINT所定义的命令则无法覆盖,一定会执行,如:

    $ docker run --rm -it entrypoint echo hello docker
    hello entrypoint echo hello docker
    
    • 1
    • 2

    实战构建redis

    $ cat redis.dockerfile
    from centos
    
    maintainer morris131<morris131@163.com>
    
    env WORK_DIR /usr/local
    
    workdir $WORK_DIR
    
    run yum install -y wget gcc gcc-c++ automake autoconf libtool make
    
    run wget https://download.redis.io/releases/redis-6.2.5.tar.gz
    
    run tar xzf redis-6.2.5.tar.gz && cd redis-6.2.5 && make
    
    expose 6379
    
    env REDIS_HOME $WORK_DIR/redis-6.2.5
    
    env PATH $PATH:$REDIS_HOME/src
    
    entrypoint ["redis-server"]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    牛客周赛 Round 15_B
    react native 毛玻璃效果
    C++模板编程(6)---实际运用模板:分离式模型(Separation Model)
    尚硅谷nginx学习笔记
    2024上海国际人工智能展(CSITF)“创新驱动发展·科技引领未来”
    Java-KoTime:接口耗时监测与邮件通知接口耗时情况
    Solidity智能合约开发 — 5.2 -理解EVM虚拟机交易执行、合约创建、区块上链
    [git] 撤销已经push的提交
    我为什么拒绝了一个5年测开经验的候选人
    leetcode每天5题-Day22
  • 原文地址:https://blog.csdn.net/u022812849/article/details/134005608