Skip to content

dockerfile命令详解

ARG

可以指定变量:

bash
ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras
ARG  CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD  /code/run-app

FROM extras:${CODE_VERSION}
CMD  /code/run-extras

也可以参数传入

bash
docker build --build-arg aaa=3 --build-arg bbb=4 -t arg-test -f 333.Dockerfile .
docker build --build-arg aaa=3 --build-arg bbb=4 -t arg-test -f 333.Dockerfile .
bash
FROM node:18-alpine3.14

ARG aaa
ARG bbb

WORKDIR /app

COPY ./test.js .

ENV aaa=${aaa} \
    bbb=${bbb}

CMD ["node", "/app/test.js"]
FROM node:18-alpine3.14

ARG aaa
ARG bbb

WORKDIR /app

COPY ./test.js .

ENV aaa=${aaa} \
    bbb=${bbb}

CMD ["node", "/app/test.js"]

FROM

  • 指明当前的镜像基于哪个镜像构建

  • dockerfile 必须以 FROM 开头,除了 ARG 命令可以在 FROM 前面

    FROM [--platform=<platform>] <image> [AS <name>]
    
    FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
    
    FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
    
  • 一个 dockerfile 可以有多个 FROM, 通过 as 指定阶段名称, Copy通过--from指定阶段

    bash
    FROM tiangolo/uvicorn-gunicorn:python3.9 as requirements-stage # 通过as 指定阶段名称
    
    COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt # --from指定阶段
    FROM tiangolo/uvicorn-gunicorn:python3.9 as requirements-stage # 通过as 指定阶段名称
    
    COPY --from=requirements-stage /tmp/requirements.txt /code/requirements.txt # --from指定阶段

LABEL

可以给镜像增加一些标签

bash
LABEL com.example.label-with-value="foo"
LABEL version="1.0"

# 换行
LABEL description="This text illustrates \
that label-values can span multiple lines."

# 一行添加多个 key=value
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"

# 换行
LABEL description="This text illustrates \
that label-values can span multiple lines."

# 一行添加多个 key=value
LABEL multi.label1="value1" multi.label2="value2" other="value3"

通过 docker inspect 查看添加的元数据

bash
docker image inspect --format='' myimage
docker image inspect --format='' myimage

WORKDIR

  • 切换到镜像中的指定路径,设置工作目录
  • 在 WORKDIR 中需要使用绝对路径,如果镜像中对应的路径不存在,会自动创建此目录
  • 一般用 WORKDIR 来替代 切换目录进行操作的指令

将宿主机的 test.txt 文件复制到 镜像的 /tmp/test.txt:

bash
WORKDIR /tmp
COPY test.txt .
WORKDIR /tmp
COPY test.txt .

如果提供了相对路径,它将相对于前一个 WORKDIR 指令的路径:

bash
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd

RUN

运行命令

bash
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' # shell模式

RUN ["executable", "param1", "param2"] # exec 模式
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME' # shell模式

RUN ["executable", "param1", "param2"] # exec 模式

CMD

bash
#  exec 形式,推荐
CMD ["executable","param1","param2"]
CMD ["可执行命令", "参数1", "参数2"...]

# 作为ENTRYPOINT的默认参数
CMD ["param1","param2"]

# shell
CMD 命令 param1 param2
#  exec 形式,推荐
CMD ["executable","param1","param2"]
CMD ["可执行命令", "参数1", "参数2"...]

# 作为ENTRYPOINT的默认参数
CMD ["param1","param2"]

# shell
CMD 命令 param1 param2
  • 一个 Dockerfile 只有一个 CMD 指令,若有多个,只有最后一个 CMD 指令生效
  • CMD 主要目的:为容器提供默认执行的命令,这个默认值可以包含可执行文件
  • 也可以不包含可执行文件,意味着必须指定 ENTRYPOINT 指令(第二种写法)

RUN 和 CMD区别:

  • RUN 可以在构建阶段运行很多个命令,而且每运行一个命令都会单独提交结果
  • CMD 在构建阶段不执行任何操作,而是指定镜像默认执行的命令

EXPOSE

bash
EXPOSE 端口号
EXPOSE 端口号/协议
EXPOSE 端口号
EXPOSE 端口号/协议

ENV

定义环境变量

bash
ENV <key>=<value> ...

# 但只能设置一个环境变量
ENV MY_VAR my-value

# 使用
WORKDIR ${MY_VAR}
# 或者
WORKDIR $MY_VAR
ENV <key>=<value> ...

# 但只能设置一个环境变量
ENV MY_VAR my-value

# 使用
WORKDIR ${MY_VAR}
# 或者
WORKDIR $MY_VAR

通过 ENV 指令可以声明环境变量,可以在以下指令中使用环境变量

  • ADD
  • COPY
  • ENV
  • EXPOSE
  • FROM
  • LABEL
  • STOPSIGNAL
  • USER
  • VOLUME
  • WORKDIR
  • ONBUILD

ARG 和 ENV 的区别

  • ARG 定义的变量只会存在于镜像构建过程,启动容器后并不保留这些变量
  • ENV 定义的变量在启动容器后仍然保留

VOLUME

运行容器时可以从本地主机或其他容器挂载数据卷,一般用来存放数据库和需要保持的数据等

bash
VOLUME ["/data"]
VOLUME ["/data"]

这里的 /data 目录就会在运行时自动挂载为匿名卷,任何向 /data 中写入的信息都不会记录进容器存储层,从而保证了容器存储层的无状态化

COPY、ADD

bash
FROM node:18-alpine3.14

ADD ./aaa.tar.gz /aaa

COPY ./aaa.tar.gz /bbb
FROM node:18-alpine3.14

ADD ./aaa.tar.gz /aaa

COPY ./aaa.tar.gz /bbb

ADD、COPY 都可以用于把目录下的文件复制到容器内的目录下。但是 ADD 还可以解压 tar.gz 文件。

打包镜像

bash
docker build -t aaa:ccc .
docker build -t aaa:ccc .

aaa 是镜像名,ccc 是镜像的标签

常见示例

Node静态服务镜像

dir
  - dockerfile
  - index.html
bash
FROM node:latest

WORKDIR /app

COPY index.html .

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install -g http-server

EXPOSE 8080

CMD ["http-server", "-p", "8080"]
FROM node:latest

WORKDIR /app

COPY index.html .

RUN npm config set registry https://registry.npmmirror.com/

RUN npm install -g http-server

EXPOSE 8080

CMD ["http-server", "-p", "8080"]

index.html拷贝到容器的/app目录下,并且在工作目录下执行http-server命令

Nest镜像

  • 新建个项目:
bash
nest new dockerfile-test -p npm
nest new dockerfile-test -p npm
  • 编写 .dockerignore:
bash
*.md
node_modules/
.git/
.DS_Store
.vscode/
.dockerignore
*.md
node_modules/
.git/
.DS_Store
.vscode/
.dockerignore
  • 编写 Dockerfile:
bash
FROM node:18.0-alpine3.14 as build-stage

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

RUN npm run build

# production stage
FROM node:18.0-alpine3.14 as production-stage

COPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.json

WORKDIR /app

RUN npm install --production

EXPOSE 3000

CMD ["node", "/app/main.js"]
FROM node:18.0-alpine3.14 as build-stage

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

RUN npm run build

# production stage
FROM node:18.0-alpine3.14 as production-stage

COPY --from=build-stage /app/dist /app
COPY --from=build-stage /app/package.json /app/package.json

WORKDIR /app

RUN npm install --production

EXPOSE 3000

CMD ["node", "/app/main.js"]
  • 执行 docker build, 镜像名为 nest、标签为 first,构建上下文是当前目录
bash
docker build -t nest:first .
docker build -t nest:first .

如果你 build 的时候报这个错误, 那需要加一行:

bash
RUN ln -s /sbin/runc /usr/bin/runc
RUN ln -s /sbin/runc /usr/bin/runc

参考

小菠萝测试笔记

感谢该作者,本文基本复制的,做了汇总