Dockerfile与镜像构建

时游大约 3 分钟

Dockerfile 与镜像构建

Dockerfile 是什么

Dockerfile 就是用来构建 docker 镜像的构建文件,就是一段命令脚本,通过脚本生成镜像。文件中的内容为 指令(大写) 参数,这里每个命令就是镜像的一层(联合文件系统)。

FROM centos

VOLUME ["volume01","volume02"]
CMD echo "-----end-----"
CMD /bin/bash
image-20220411233221809
image-20220411233221809

常用指令

指令说明示例
FROM基础镜像,一切从这里开始FROM node:16
MAINTAINER作者信息(新写法 LABEL)LABEL author="sunshine"
RUN构建镜像时执行的命令(每个 RUN 一层)RUN npm install
COPY从构建上下文复制文件进镜像COPY . /app
ADD类似 COPY,会自动解压 tar、支持 URLADD jdk.tar.gz /opt
WORKDIR设置工作目录WORKDIR /app
ENV构建时环境变量ENV NODE_ENV production
EXPOSE声明容器监听端口(仅声明,映射靠 -p)EXPOSE 80
VOLUME匿名挂载数据卷VOLUME ["/data"]
CMD容器启动时执行的命令,只有最后一条生效,可被 run 参数覆盖CMD ["nginx","-g","daemon off;"]
ENTRYPOINT同 CMD,但参数会追加而不是覆盖ENTRYPOINT ["java","-jar","app.jar"]
ONBUILD构建子镜像时触发ONBUILD RUN npm build
ARG构建参数(docker build --build-arg 传入)ARG VERSION=1.0

CMD 与 ENTRYPOINT 的区别:docker run image ls -a 时,CMD 定义的整体被 ls -a 替换;ENTRYPOINT 则把 ls -a 追加在其后执行。

构建与推送

# -f 指定 Dockerfile 路径,-t 名字:tag,最后的 . 是构建上下文目录
docker build -f Dockerfile -t myapp:1.0 .

# 运行验证
docker run -d -p 8080:80 myapp:1.0

# 登录仓库推送(docker hub / harbor / 阿里云镜像仓库)
docker login
docker tag myapp:1.0 username/myapp:1.0
docker push username/myapp:1.0

.dockerignore

构建上下文中有时候不该把所有文件发给 docker daemon:

node_modules
dist
.git
*.log
.dockerignore
Dockerfile

Demo 1:构建自己的 CentOS(带 vim/ifconfig)

FROM centos
MAINTAINER sunshine

ENV MYPATH /usr/local
WORKDIR $MYPATH

RUN yum -y install vim
RUN yum -y install net-tools

EXPOSE 80

CMD echo $MYPATH
CMD echo "-----end-----"
CMD /bin/bash

对比:官方 centos 镜像没有 vim、ifconfig,通过 Dockerfile 增强后打包成自己的镜像,这就是"镜像分层增量构建"的意义。

Demo 2:多阶段构建前端项目(Vue/React 通用)

一次构建同时用到 node(构建)和 nginx(运行),最终镜像只保留 nginx 层,体积从 1GB+ 降到 20MB 级:

# ========== 阶段1:构建 ==========
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install --registry=https://registry.npmmirror.com
COPY . .
RUN npm run build

# ========== 阶段2:运行 ==========
FROM nginx:1.21
# 从 builder 阶段拷贝构建产物,注意 --from
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

配套 nginx.conf(history 路由兜底):

server {
    listen 80;
    server_name localhost;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;   # vue-router history 模式刷新 404 兜底
    }
}
docker build -t blog-web:1.0 .
docker run -d -p 8080:80 --name blog-web blog-web:1.0

构建优化建议

  1. 尽量使用小基础镜像:alpine / slim 版本(如 node:16-alpine)
  2. 依赖文件先 COPY 再 install(利用层缓存,代码变动不会重装依赖)
  3. 多阶段构建,构建工具链不进最终镜像
  4. 合并 RUN 并清理缓存:RUN npm install && npm cache clean --force && rm -rf /var/cache/apk/*
  5. .dockerignore 排除无用文件,加快上下文传输
Loading...