dockerfile 构建项目镜像
一、通用打包原则
- 采用 轻量化基础镜像(如 slim,alpine版本)减少镜像体积
- 分层构建/复制,利用Docker缓存机制,加速构建;
- 非root用户运行容器,提升安全性
- 明确暴露端口、指定启动命令,规范容器启动;
- 分离依赖安装与代码复制(先装依赖,再复制代码,避免依赖变更时重复构建)。
二、FastAPI项目 Dockerfile
-
项目目录结构
fastapi-project/ ├── app/ # 项目核心代码 │ ├── __init__.py │ ├── main.py # 入口文件(含 FastAPI 实例) │ └── routes/ # 路由模块(可选) ├── requirements.txt # 依赖清单 └── Dockerfile # 本次编写的 Dockerfile -
requirements.txt 示例
fastapi==0.104.1 uvicorn[standard]==0.24.0 # ASGI 服务器(standard 含 websocket 支持) python-multipart==0.0.6 # 处理表单数据(可选) pydantic==2.5.2 # 数据校验(FastAPI 依赖) -
Dockerfile 完整代码
# 阶段1:基础镜像(Python 3.11 轻量化版本,含基础编译环境) FROM python:3.11-slim AS base # 设置环境变量:Python 不生成 .pyc 文件,不缓冲输出 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 # 设置工作目录(容器内) WORKDIR /app # 安装系统依赖(解决 Python 依赖编译问题,如 cryptography) RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libpq-dev \ # 若使用 PostgreSQL 数据库需添加(可选) && rm -rf /var/lib/apt/lists/* # 清理缓存,减少镜像体积 # 阶段2:安装依赖(利用 Docker 缓存,依赖不变则不重新构建) FROM base AS deps # 复制依赖清单到容器 COPY requirements.txt . # 升级 pip,安装依赖到指定目录(便于后续复制) RUN pip install --upgrade pip && \ pip install --no-cache-dir -r requirements.txt -t /app/deps # 阶段3:构建最终镜像(仅包含运行时依赖,最小化体积) FROM base AS final # 创建非 root 用户(安全最佳实践) RUN groupadd -r appuser && useradd -r -g appuser appuser # 复制依赖(从 deps 阶段) COPY --from=deps /app/deps /app/deps # 将依赖目录添加到 Python 路径 ENV PYTHONPATH=/app/deps # 复制项目代码(仅复制必要文件,避免冗余) COPY ./app /app/app # 切换到非 root 用户 USER appuser # 暴露 FastAPI 运行端口(与 uvicorn 启动命令一致) EXPOSE 8000 # 启动命令:uvicorn 启动 FastAPI,支持热重载(生产环境关闭 reload) CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"] -
构建与运行命令
# 构建镜像(镜像名 fastapi-app,标签 v1) docker build -t fastapi-app:v1 . # 运行容器(端口映射 8000:8000,后台运行,容器名 fastapi-server) docker run -d -p 8000:8000 --name fastapi-server fastapi-app:v1 # 查看日志 docker logs -f fastapi-server -
关键说明
- workers 数量:推荐设置为
CPU核心数 * 2 + 1(如 4 核 CPU 设为 9); - 生产环境优化:关闭
--reload,添加--proxy-headers(支持反向代理); - 镜像体积:slim 基础镜像约 100MB,最终镜像约 150-200MB(远小于完整版 Python 镜像)。
- workers 数量:推荐设置为
三、django 项目构建Dockerfile
-
项目目录
django-project/ ├── project/ # 项目配置目录(django-admin startproject 生成) │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── app/ # 业务应用(python manage.py startapp app) ├── static/ # 静态文件(收集后目录) ├── media/ # 媒体文件(用户上传) ├── requirements.txt # 依赖清单 ├── manage.py └── Dockerfile -
requirements.txt 示例
django==4.2.7 gunicorn==21.2.0 # WSGI 服务器(生产环境替代 runserver) whitenoise==6.5.0 # 静态文件服务(无需 Nginx 也可提供静态文件) psycopg2-binary==2.9.9 # PostgreSQL 驱动(可选,根据数据库调整) django-cors-headers==4.3.0 # 跨域支持(可选) -
Dockerfile 完整代码
# 基础镜像(Python 3.11 轻量化版本) FROM python:3.11-slim # 环境变量配置 ENV PYTHONDONTWRITEBYTECODE=1 ENV PYTHONUNBUFFERED=1 ENV DJANGO_SETTINGS_MODULE=project.settings # 指定 Django 配置文件 ENV DJANGO_DEBUG=False # 生产环境关闭 Debug # 工作目录 WORKDIR /app # 安装系统依赖(解决 psycopg2 等依赖编译问题) RUN apt-get update && apt-get install -y --no-install-recommends \ gcc \ libpq-dev \ && rm -rf /var/lib/apt/lists/* # 升级 pip,安装依赖 COPY requirements.txt . RUN pip install --upgrade pip && \ pip install --no-cache-dir -r requirements.txt # 复制项目代码 COPY . . # 收集静态文件(Django 必须步骤,需确保 settings.py 配置 STATIC_ROOT) RUN python manage.py collectstatic --noinput # 创建非 root 用户 RUN groupadd -r djangouser && useradd -r -g djangouser djangouser # 授权静态文件和媒体文件目录(避免权限问题) RUN chown -R djangouser:djangouser /app/static /app/media USER djangouser # 暴露端口(gunicorn 运行端口) EXPOSE 8000 # 启动命令:gunicorn 启动 Django,配合 whitenoise 提供静态文件 CMD ["gunicorn", "--bind", "0.0.0.0:8000", "--workers", "4", "project.wsgi:application"] -
Django 配置补充(settings.py)
需配合Dockerfile调整以下配置:
# 允许所有主机访问(生产环境需指定具体域名,如 ALLOWED_HOSTS = ["api.example.com"]) ALLOWED_HOSTS = ["*"] # 静态文件配置(配合 whitenoise) STATIC_URL = "/static/" STATIC_ROOT = BASE_DIR / "static" # 与 Dockerfile 中 collectstatic 对应 STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" # 媒体文件配置(可选,用户上传文件存储目录) MEDIA_URL = "/media/" MEDIA_ROOT = BASE_DIR / "media" -
构建与运行命令
# 构建镜像 docker build -t django-app:v1 . # 运行容器(映射端口 8000:8000,挂载媒体文件目录(持久化)) docker run -d -p 8000:8000 \ -v ./media:/app/media \ # 本地目录挂载到容器,持久化用户上传文件 --name django-server django-app:v1 # 执行数据库迁移(首次运行或模型变更时) docker exec -it django-server python manage.py migrate -
关键说明
- 静态文件:生产环境推荐用 Nginx 代理静态文件(性能更好),此时可删除
whitenoise依赖,Dockerfile 中无需collectstatic; - 数据库:若使用外部数据库(如 MySQL/PostgreSQL),需通过环境变量传递连接信息(如
DJANGO_DB_HOST),避免硬编码; - 安全优化:生产环境需设置
SECRET_KEY为环境变量,禁止ALLOWED_HOSTS = ["*"]。
- 静态文件:生产环境推荐用 Nginx 代理静态文件(性能更好),此时可删除
四、SpringBoot项目Dockerfile
-
项目目录结构
springboot-project/ ├── src/ # 源代码目录 ├── pom.xml # Maven 依赖配置(若用 Gradle 则为 build.gradle) └── Dockerfile -
核心依赖(pom.xml)
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>3.2.0</version> # 与 SpringBoot 版本一致 <executions> <execution> <goals> <goal>repackage</goal> # 打包为可执行 jar </goals> </execution> </executions> </plugin> </plugins> </build> -
dockerfile
采用 多阶段构建 分离构建环境和运行环境,最小化镜像体积
# 阶段1:构建阶段(使用 Maven 镜像编译打包) FROM maven:3.8.8-openjdk17 AS builder # 工作目录 WORKDIR /app # 复制 Maven 配置文件(先复制 pom.xml,利用缓存) COPY pom.xml . # 下载依赖(依赖不变时,直接使用缓存,无需重新下载) RUN mvn dependency:go-offline -B # 复制源代码 COPY src ./src # 编译打包(跳过测试,加速构建) RUN mvn clean package -DskipTests # 提取可执行 jar 包(SpringBoot 打包后在 target 目录,名称格式:项目名-版本.jar) # 此处假设打包后的 jar 名为 app.jar(可通过 pom.xml 配置 finalName 固定名称) RUN cp target/*.jar app.jar && \ # 解压 jar 包(优化运行时启动速度,可选) java -Djarmode=layertools -jar app.jar extract # 阶段2:运行阶段(使用轻量级 OpenJDK 镜像,仅含运行时) FROM openjdk:17-jdk-slim # 环境变量配置(SpringBoot 配置) ENV SPRING_PROFILES_ACTIVE=prod # 激活生产环境配置 ENV JAVA_OPTS="-Xms512m -Xmx1024m" # JVM 内存配置(根据服务器调整) # 工作目录 WORKDIR /app # 从构建阶段复制解压后的分层文件(利用 Docker 缓存,加速启动) COPY --from=builder /app/dependencies/ ./ COPY --from=builder /app/spring-boot-loader/ ./ COPY --from=builder /app/snapshot-dependencies/ ./ COPY --from=builder /app/application/ ./ # 创建非 root 用户 RUN groupadd -r springuser && useradd -r -g springuser springuser USER springuser # 暴露 SpringBoot 默认端口 EXPOSE 8080 # 启动命令(通过 SpringBoot 分层启动器启动,优化内存和启动速度) ENTRYPOINT ["sh", "-c", "java ${JAVA_OPTS} org.springframework.boot.loader.launch.JarLauncher"] -
简化版 Dockerfile(单阶段,适合快速测试)
若无需分层优化,可使用单阶段构建(镜像体积稍大):
FROM openjdk:17-jdk-slim WORKDIR /app # 复制本地打包好的 jar 包到容器(需先本地执行 mvn package) COPY target/*.jar app.jar ENV SPRING_PROFILES_ACTIVE=prod EXPOSE 8080 # 直接启动 jar 包 ENTRYPOINT ["java", "-jar", "app.jar"] -
构建与运行命令
# 多阶段构建(推荐) docker build -t springboot-app:v1 . # 运行容器(端口映射 8080:8080,传递环境变量) docker run -d -p 8080:8080 \ -e SPRING_DATASOURCE_URL=jdbc:mysql://mysql-host:3306/dbname \ # 数据库连接(示例) -e SPRING_DATASOURCE_USERNAME=root \ -e SPRING_DATASOURCE_PASSWORD=123456 \ --name springboot-server springboot-app:v1 # 查看日志 docker logs -f springboot-server -
关键说明
- 多阶段构建优势:构建阶段镜像约 1GB+,运行阶段镜像仅 300-400MB(大幅减少部署体积);
- JVM 优化:通过
JAVA_OPTS调整堆内存(-Xms初始内存,-Xmx最大内存),避免内存溢出; - 配置方式:生产环境通过环境变量(
-e参数)传递配置,避免硬编码application.yml; - 镜像选择:
openjdk:17-jdk-slim适合需要运行时编译的场景,openjdk:17-jre-slim体积更小(仅含 JRE,无 JDK)。

浙公网安备 33010602011771号