ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Docker 容器化部署实战:从零搭建你的第一个生产级环境

Docker 容器化部署实战:从零搭建你的第一个生产级环境

Docker 容器化部署实战:从零搭建你的第一个生产级环境


前言

“在我机器上明明能跑啊!”

这句话大概是每个开发者都说过(或听过)的经典台词。而Docker的出现,正是为了彻底终结这个世纪难题。

本文将从核心概念出发,带你一步步完成一个真实项目的容器化部署,涵盖 Dockerfile 编写、镜像构建、多容器编排(Docker Compose),以及生产环境中的最佳实践。


一、Docker 到底是什么?

一句话理解

Docker 是一个轻量级的虚拟化平台,它把你的应用程序和所有依赖(运行环境、系统库、配置文件)打包成一个标准化的单元——容器(Container),保证在任何机器上都能一致运行。

容器 vs 虚拟机

对比维度虚拟机(VM)容器(Container)
启动速度分钟级秒级甚至毫秒级
资源占用GB 级别MB 级别
隔离程度完全隔离(含 OS)进程级隔离(共享内核)
镜像体积数 GB数十 ~ 数百 MB
运行密度一台机器跑十几个一台机器跑上百个

💡 简单类比:虚拟机像独栋别墅(自带地基和水电),容器像集装箱公寓(共享大楼基础设施,但各自独立)。


二、核心概念速览

在动手之前,先搞懂三个核心概念:

  • 镜像(Image):只读的应用模板,包含代码 + 运行时 + 依赖,相当于"安装包"
  • 容器(Container):镜像的运行实例,相当于"正在运行的程序"
  • 仓库(Registry):存放和分发镜像的地方,Docker Hub 是最大的公共仓库

它们的关系:仓库 → 拉取镜像 → 运行容器

# 从仓库拉取镜像并运行容器(一条命令搞定)dockerrun-d-p8080:80 nginx

这条命令做了什么?

  1. 检查本地是否有nginx镜像 → 没有则从 Docker Hub 拉取
  2. 以后台模式(-d)启动容器
  3. 将宿主机的8080端口映射到容器的80端口

三、实战:容器化一个 Python Flask 应用

我们从一个真实场景出发:将一个 Flask API 服务容器化部署。

3.1 项目结构

flask-app/ ├── app.py # Flask 应用代码 ├── requirements.txt # Python 依赖 ├── Dockerfile # Docker 构建文件 └── docker-compose.yml # 多容器编排文件

3.2 应用代码

app.py

fromflaskimportFlask,jsonifyimportdatetimeimportos app=Flask(__name__)@app.route("/")defhome():returnjsonify({"message":"Hello from Docker! 🐳","hostname":os.uname().nodename,"time":datetime.datetime.now().isoformat()})@app.route("/health")defhealth():returnjsonify({"status":"healthy"}),200if__name__=="__main__":app.run(host="0.0.0.0",port=5000)

requirements.txt

flask==3.0.0 gunicorn==21.2.0

3.3 编写 Dockerfile

Dockerfile 是构建镜像的"配方",告诉 Docker 如何一步步打包你的应用:

# 1. 选择基础镜像(Python 官方镜像,slim 版本更小) FROM python:3.11-slim # 2. 设置工作目录 WORKDIR /app # 3. 先复制依赖文件,利用 Docker 缓存层加速构建 COPY requirements.txt . # 4. 安装依赖 RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 5. 复制应用代码 COPY . . # 6. 暴露端口(仅声明,实际映射靠 docker run -p) EXPOSE 5000 # 7. 启动命令(使用 gunicorn 作为生产级 WSGI 服务器) CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]
Dockerfile 最佳实践要点
实践说明
使用 slim/alpine 基础镜像体积更小,攻击面更少
先 COPY 依赖再 COPY 代码依赖不变时命中缓存,加速构建
--no-cache-dir不缓存 pip 下载包,减小镜像体积
使用.dockerignore排除.git__pycache__venv等无用文件
非 root 用户运行提升安全性(下面会讲)

创建.dockerignore文件:

.git __pycache__ *.pyc venv/ .env

3.4 构建与运行

# 构建镜像(注意最后的 . 表示构建上下文)dockerbuild-tflask-app:1.0.# 运行容器dockerrun-d\--namemy-flask-app\-p8080:5000\--restartunless-stopped\flask-app:1.0# 验证curlhttp://localhost:8080/# 输出: {"hostname":"abc123def","message":"Hello from Docker! 🐳","time":"2026-08-15T13:25:00"}

常用参数说明:

  • -d:后台运行
  • --name:给容器起个名字,方便管理
  • -p 宿主机端口:容器端口:端口映射
  • --restart unless-stopped:异常退出时自动重启

四、进阶:Docker Compose 多容器编排

真实项目中,你的应用通常不止一个容器——还需要数据库、缓存、消息队列等。手动管理多个docker run命令既不优雅也不可持续。

Docker Compose让你用一个 YAML 文件定义和运行多容器应用。

4.1 场景:Flask + Redis + Nginx

我们用 Compose 编排三个服务:

  • Flask API:业务逻辑
  • Redis:缓存层
  • Nginx:反向代理 + 静态资源服务

4.2 docker-compose.yml

version:"3.8"services:# Flask API 服务web:build:.container_name:flask-appports:-"5000:5000"environment:-REDIS_HOST=redis-FLASK_ENV=productiondepends_on:redis:condition:service_healthyrestart:unless-stoppednetworks:-app-network# Redis 缓存服务redis:image:redis:7-alpinecontainer_name:redis-cacheports:-"6379:6379"volumes:-redis-data:/datahealthcheck:test:["CMD","redis-cli","ping"]interval:10stimeout:5sretries:3restart:unless-stoppednetworks:-app-network# Nginx 反向代理nginx:image:nginx:alpinecontainer_name:nginx-proxyports:-"80:80"volumes:-./nginx.conf:/etc/nginx/conf.d/default.conf:rodepends_on:-webrestart:unless-stoppednetworks:-app-network# 数据卷(持久化 Redis 数据)volumes:redis-data:# 自定义网络networks:app-network:driver:bridge

4.3 Nginx 配置

nginx.conf

upstream flask_backend { server web:5000; } server { listen 80; server_name localhost; location / { proxy_pass http://flask_backend; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }

4.4 一键启动

# 启动所有服务(后台运行)dockercompose up-d# 查看运行状态dockercomposeps# 输出示例:# NAME IMAGE STATUS PORTS# flask-app flask-app:1.0 Up 5 seconds 0.0.0.0:5000->5000/tcp# redis-cache redis:7-alpine Up 6 seconds 0.0.0.0:6379->6379/tcp# nginx-proxy nginx:alpine Up 5 seconds 0.0.0.0:80->80/tcp# 查看日志dockercompose logs-fweb# 停止所有服务dockercompose down# 停止并清除数据卷dockercompose down-v

🎯 只需要一个命令docker compose up -d,三个服务全部启动,网络互通,依赖自动排序。


五、生产环境最佳实践

5.1 镜像瘦身

# ❌ 不推荐:完整 Python 镜像,约 900MB FROM python:3.11 # ✅ 推荐:slim 版本,约 150MB FROM python:3.11-slim # ✅✅ 进阶:多阶段构建,最终镜像可压缩到 50MB 以下 FROM python:3.11-slim AS builder WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir --prefix=/install -r requirements.txt FROM python:3.11-alpine WORKDIR /app COPY --from=builder /install /usr/local COPY . . CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:5000", "app:app"]

5.2 安全性加固

# 创建非 root 用户运行应用 RUN adduser --disabled-password --gecos '' appuser USER appuser

5.3 健康检查

# docker-compose.yml 中添加健康检查services:web:build:.healthcheck:test:["CMD","curl","-f","http://localhost:5000/health"]interval:30stimeout:10sretries:3start_period:10s

5.4 环境变量管理

# .env 文件(不要提交到 Git!)FLASK_ENV=productionDATABASE_URL=postgresql://user:pass@db:5432/mydbREDIS_URL=redis://redis:6379/0SECRET_KEY=your-super-secret-key
# docker-compose.yml 中引用services:web:env_file:-.env

六、常用命令速查表

# ========== 镜像操作 ==========dockerbuild-tmyapp:1.0.# 构建镜像dockerimages# 列出本地镜像dockerrmi<image_id># 删除镜像dockertag myapp:1.0 user/myapp:1.0# 打标签dockerpush user/myapp:1.0# 推送到仓库dockerpull nginx:latest# 拉取镜像# ========== 容器操作 ==========dockerrun-d-p8080:80 nginx# 运行容器dockerps# 查看运行中的容器dockerps-a# 查看所有容器(含已停止)dockerlogs-f<container># 查看日志dockerexec-it<container>/bin/sh# 进入容器dockerstop<container># 停止容器dockerrm<container># 删除容器dockerstats# 查看资源使用情况# ========== 清理 ==========dockersystem prune-a# 清理所有未使用的资源(慎用!)dockervolume prune# 清理未使用的数据卷

七、总结

阶段关键动作
理解概念镜像 = 模板,容器 = 实例,仓库 = 商店
编写 Dockerfile选小基础镜像、利用缓存层、.dockerignore
构建与运行docker builddocker run
多容器编排Docker Compose 一键管理
生产部署镜像瘦身 + 安全加固 + 健康检查 + 环境变量管理

Docker 的价值不仅仅是"解决环境一致性问题",它更是现代云原生架构的基石——CI/CD 流水线、微服务部署、弹性伸缩,都离不开它。

返回列表