Skip to content

Dockerfile配置

字段详解

  • FROM <IMAGE>:<TAG> 指定基础镜像,不填写tag默认latest; 不同阶段可指定不同FROM

  • RUN npm install 镜像**构建时(build)**运行的命令

多条RUN指令可以合并为一条,在构建的时候会减少产生中间层镜像,eg: RUN npm config set registry https://registry.npm.taobao.org && npm install

  • CMD ["npm", "start"] 镜像**运行时(run)**运行的命令; 如果docker run时指定了运行的命令,则CMD命令不会执行

  • ENTRYPOINT ["npm", "start"] 镜像**运行时(run)**运行的命令; 不会被docker run时指定的运行命令覆盖

  • WORKDIR /web 设置容器内部工作目录,这样ENTRYPOINT和CMD指定的命令都会在容器中这个目录下进行【注意:COPY/ADD还是需要指定绝对路径, eg: COPY package.json /web】

  • COPY dist / 复制文件; 前者为源文件路径,使用Dockerfile上下文相对路径, 会将dist下所有文件复制到容器内目标路径(当指定--from=xxx时,这个路径为build时构建产物,多阶段构建时用到);后者为目标路径, 容器内绝对路径(该路径不存在时会自动创建)

  • ADD package.json / 同COPY指令; 具备解压功能

  • ENV HOST 0.0.0.0 设置容器内全局环境变量

  • VOLUME ["/etc/nginx/nginx.conf", "/usr/share/nginx/html"] 匿名挂载目录

  • EXPOSE 容器内暴露出来的端口

  • ONBUILD COPY index.html /var/www/html 当一个镜像被用作其他镜像的基础镜像时,这个触发器会被执行

  • ARG TARGET_DIR=/app-web 变量,构建时可指定 --build-arg <varname>=<value>; 示例:WORKDIR ${TARGET_DIR}

  • MAINTAINER 作者信息(已废弃)

Dockerfile实例

基本构建镜像

docker
# Docker环境声明,不存在则从dockerHub拉取
FROM node:12.18.4
# author
MAINTAINER chaoszhu
# 配置容器的系统环境变量: default_value默认为 '', 可在构建时指定 --build-arg cur_env=dev
# 构建时可传递
ARG cur_env=default_value
ENV CUR_ENV=$cur_env
# 或者直接写死
ENV NODE_ENV production
ENV HOST 0.0.0.0

# 该阶段容器运行时 CMD 命令会基于该目录
WORKDIR /app

# 复制package.json到镜像根目录
COPY package.json /app
# 锁定依赖
COPY package-lock.json /app

# 设置taobao源
RUN npm config set registry https://registry.npm.taobao.org

# 安装依赖
RUN npm install

# 复制项目目录所有文件到工作目录
COPY . /app

# 打包
RUN npm run build

# 镜像暴露的端口(同nuxt.config.js配置的端口,默认3000)
EXPOSE 3000

# docker run 才跑的命令
CMD ["npm", "start"]

多阶段镜像构建

仅构建nginx镜像

docker
# stage0
# As:自定义一个临时镜像名称【后面的阶段可以用到】
FROM node As builder
WORKDIR /app
# copy项目工程到 /app
COPY . .
# 安装依赖
RUN npm install
# 打包
RUN npm run build

# stage1
FROM nginx
# --from:指定stage0(builder)构建的目录, copy dist目录下所有文件到当前镜像的/usr/share/nginx/html下
COPY --from=builder dist /usr/share/nginx/html
EXPOSE 80

构建镜像命令

docker build --build-arg cur_env=uat -t imagesName:Tag . 最后一个点表示当前文件夹

  • --build-arg cur_env=uat 指定Dockerfile配置文件中$cur_env变量
  • -t为指定镜像名称与版本号(tag)
  • 最后的点表示为当前目录为docker构建镜像的上下文环境目录

WARNING

docker构建时必须指定相同imagesName,否则无法使用docker的分层缓存机制(tag允许不同)

分层缓存机制

分层缓存机制参考文章

  • Docker构建是分层的,一条指令一层,在没有带--no-cache=true指令的情况下如果某一层没有改动,Docker就不会重新构建这一层而是会使用缓存,如果第n层有改动,则n层以后的缓存都会失效
  • 大多数情况下判断有无改动的方法是判断这层的指令和缓存中的构建指令是否一致,但是对于COPY和ADD命令会比较镜像内的文件和构建目录文件的做校验来判断本层是否有改动. 首次npm install会比较慢, 但得益于docker打包镜像的分层缓存机制. 在package.json文件没修改过的前提下第二次构建会使用上一次的缓存。因此,如果package.json文件被修改过,则RUN npm install会被重新执行

【待解决问题】

  • 每次构建完成会生成不一样的imagesID,考虑如何干掉原有的已启动容器,然后运行新构建的镜像

挑选合适的docker node镜像

https://github.com/docker-library/official-images/blob/master/library/node

js
node:<version>
基于Debian,官方默认镜像。当你不确定你需要什么的时候选择这个就对了。用作构建源码使用,体积挺大。


node:<version>-slim
基于Debian,删除了很多默认公共的软件包,只有node运行的最小环境。除非你有空间限制,否则推荐使用默认镜像。

node:<version>-alpine
基于alpine,比Debian小的多。如果想要最小的镜像,可以选择这个做为base。需要注意的是,alpine使用musl代替glibc。一些c环境的软件可能不兼容。但大部分没问题。