第7课:Dockerfile 详解

【腾讯云】语音识别准确率高,支持多语种,多场景,限时特惠,最低14.9元起

推广

【腾讯云】语音识别准确率高,支持多语种,多场景,限时特惠,最低14.9元起

Dockerfile基础

Dockerfile是用来构建Docker镜像的文本文件,包含了一系列指令和参数。通过Dockerfile,我们可以自动化地创建自定义镜像。

什么是Dockerfile?

Dockerfile是一个包含指令的文本文件,Docker可以读取这些指令来自动构建镜像。每个指令都会在镜像中创建一个新的层。

Dockerfile的基本结构

# 注释
FROM base_image
MAINTAINER author_info
RUN command
COPY source dest
CMD ["executable", "param1", "param2"]

常用指令详解

FROM - 基础镜像

# 指定基础镜像
FROM ubuntu:20.04

# 使用官方镜像
FROM node:16-alpine

# 多阶段构建
FROM node:16 AS builder
FROM nginx:alpine AS runtime

RUN - 执行命令

# 执行shell命令
RUN apt-get update && apt-get install -y curl

# 使用exec形式
RUN ["apt-get", "update"]

# 多行命令
RUN apt-get update && \
    apt-get install -y \
        curl \
        wget \
        vim && \
    apt-get clean

COPY和ADD - 复制文件

# 复制文件
COPY app.js /app/
COPY package*.json /app/

# 复制目录
COPY src/ /app/src/

# ADD可以处理URL和压缩文件
ADD https://example.com/file.tar.gz /app/
ADD archive.tar.gz /app/

WORKDIR - 工作目录

# 设置工作目录
WORKDIR /app

# 相对路径
WORKDIR src
WORKDIR ../config

ENV - 环境变量

# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000

# 多个变量
ENV NODE_ENV=production \
    PORT=3000 \
    DEBUG=false

EXPOSE - 暴露端口

# 暴露端口
EXPOSE 80
EXPOSE 443
EXPOSE 3000/tcp
EXPOSE 53/udp

CMD和ENTRYPOINT - 启动命令

# CMD - 默认命令(可被覆盖)
CMD ["nginx", "-g", "daemon off;"]
CMD npm start

# ENTRYPOINT - 入口点(不可被覆盖)
ENTRYPOINT ["docker-entrypoint.sh"]
ENTRYPOINT ["nginx"]

# 组合使用
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]

实际应用示例

Node.js应用Dockerfile

# 使用官方Node.js镜像
FROM node:16-alpine

# 设置工作目录
WORKDIR /app

# 复制package文件
COPY package*.json ./

# 安装依赖
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 创建非root用户
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

# 更改文件所有者
USER nextjs

# 暴露端口
EXPOSE 3000

# 启动应用
CMD ["npm", "start"]

Python应用Dockerfile

FROM python:3.9-slim

# 设置环境变量
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# 设置工作目录
WORKDIR /app

# 安装系统依赖
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        gcc \
        && rm -rf /var/lib/apt/lists/*

# 复制requirements文件
COPY requirements.txt .

# 安装Python依赖
RUN pip install --no-cache-dir -r requirements.txt

# 复制应用代码
COPY . .

# 创建非root用户
RUN useradd --create-home --shell /bin/bash app
USER app

# 暴露端口
EXPOSE 8000

# 启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Java应用Dockerfile

# 多阶段构建
FROM maven:3.8-openjdk-11 AS builder

WORKDIR /app
COPY pom.xml .
COPY src ./src

# 构建应用
RUN mvn clean package -DskipTests

# 运行时镜像
FROM openjdk:11-jre-slim

WORKDIR /app

# 复制jar文件
COPY --from=builder /app/target/*.jar app.jar

# 创建用户
RUN useradd --create-home --shell /bin/bash app
USER app

# 暴露端口
EXPOSE 8080

# 启动应用
ENTRYPOINT ["java", "-jar", "app.jar"]

多阶段构建

基本多阶段构建

# 构建阶段
FROM node:16 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

复杂多阶段构建

# 依赖安装阶段
FROM node:16-alpine AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

# 构建阶段
FROM node:16-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 运行阶段
FROM node:16-alpine AS runner
WORKDIR /app
ENV NODE_ENV production

RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001

COPY --from=deps /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist

USER nextjs
EXPOSE 3000
CMD ["npm", "start"]

构建镜像

基本构建命令

# 构建镜像
docker build -t my-app:latest .

# 指定Dockerfile
docker build -f Dockerfile.prod -t my-app:prod .

# 构建时传递参数
docker build --build-arg NODE_ENV=production -t my-app .

# 不使用缓存
docker build --no-cache -t my-app .

构建参数(ARG)

# 定义构建参数
ARG NODE_VERSION=16
ARG BUILD_ENV=production

FROM node:${NODE_VERSION}-alpine

# 在RUN中使用参数
RUN echo "Building for ${BUILD_ENV}"

# 转换为环境变量
ENV BUILD_ENV=${BUILD_ENV}
# 传递构建参数
docker build --build-arg NODE_VERSION=18 --build-arg BUILD_ENV=staging -t my-app .

最佳实践

1. 镜像大小优化

# 使用Alpine镜像
FROM node:16-alpine

# 合并RUN指令
RUN apt-get update && \
    apt-get install -y package && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 使用.dockerignore
# .dockerignore文件内容:
node_modules
.git
.gitignore
README.md
Dockerfile
.dockerignore

2. 缓存优化

# 先复制依赖文件
COPY package*.json ./
RUN npm install

# 再复制源代码
COPY . .

3. 安全最佳实践

# 使用非root用户
RUN useradd --create-home --shell /bin/bash app
USER app

# 只复制必要文件
COPY --chown=app:app src/ ./src/

# 使用特定版本标签
FROM node:16.14.2-alpine

4. 健康检查

# 添加健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

调试技巧

1. 分层构建调试

# 查看镜像历史
docker history my-app:latest

# 运行中间层进行调试
docker run -it <intermediate-image-id> /bin/sh

2. 构建过程调试

# 显示构建过程
docker build --progress=plain -t my-app .

# 保留中间容器
docker build --rm=false -t my-app .

常见问题解决

1. 构建缓存问题

# 清除构建缓存
docker builder prune

# 查看缓存使用情况
docker system df

2. 权限问题

# 确保文件权限正确
COPY --chown=app:app . .
RUN chmod +x entrypoint.sh

3. 时区问题

# 设置时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

小结

本课学习了Dockerfile的核心内容:

  • Dockerfile基本语法和指令
  • 实际应用场景的Dockerfile编写
  • 多阶段构建技术
  • 镜像构建和优化
  • 最佳实践和调试技巧

掌握Dockerfile是创建高质量Docker镜像的关键技能。下一课我们将学习Docker Compose的使用。

Vue3 + TypeScript 企业级项目实战

课程推荐

Vue3 + TypeScript 企业级项目实战
Python 全栈开发工程师培训

热门课程

Python 全栈开发工程师培训

📚 文章对你有帮助?请关注我的公众号,万分感谢!

获取更多优质技术文章,第一时间掌握最新技术动态

关注公众号

关注公众号

第一时间获取最新技术文章

添加微信

添加微信

技术交流 · 问题答疑 · 学习指导

评论讨论

欢迎留下你的想法和建议