news 2026/8/21 20:20:51

从零到精通:Docker容器化完整指南与实战练习

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从零到精通:Docker容器化完整指南与实战练习

目录

引言

基础练习

练习 1:基础镜像和命令使用

练习 2:Python 应用构建

练习 3:Rust 多阶段构建

基础部分提交查看分数

专业练习

练习 1: Docker 存储管理与 Volume 持久化

练习 2:Docker 网络管理与自定义 Bridge

练习 3:Docker Compose 多容器编排

专业部分提交查看分数

总结


引言

本文通过一套由浅入深、循序渐进的实战练习,系统性地展示了Docker的核心概念与实际应用。从最基础的镜像构建与容器运行,到复杂的多阶段构建优化;从单服务容器化,到多容器应用的网络配置与数据持久化编排,每一部分均配有清晰的代码示例、分步操作说明和验证方法。无论你是刚刚接触容器技术的初学者,还是希望巩固和深化实战经验的开发者,都能通过这些练习快速掌握Docker的核心技能,并搭建起可在生产环境中参考的容器化应用模型。

题目来自2025 第二期 Docker 训练营

2025 第二期 Docker 训练营地址:https://opencamp.cn/Docker/camp/202502/register?code=dxJSEQUgrBdWs

基础练习

练习 1:基础镜像和命令使用

  • 使用ubuntu:22.04作为基础镜像

  • 安装nginxcurl

  • 创建一个简单的 HTML 文件,内容为"Hello Docker!"

  • 将该 HTML 文件复制到 Nginx 的默认网站目录

  • 暴露 80 端口并启动 Nginx 服务

给Dockerfile文件添加以下代码

FROM ubuntu:22.04 # 在这里编写你的 Dockerfile 指令 # 避免在交互式安装时卡住 ENV DEBIAN_FRONTEND=noninteractive # 更新 apt 并安装 nginx、curl;安装后清理 apt 缓存以减小镜像体积 RUN apt-get update \ && apt-get install -y --no-install-recommends nginx curl \ && rm -rf /var/lib/apt/lists/* # 确保 nginx 默认网站目录存在(通常已存在),并创建一个简单的 HTML 文件 RUN mkdir -p /var/www/html \ && cat > /var/www/html/index.html <<'EOF' Hello Docker! EOF # 暴露 HTTP 默认端口 EXPOSE 80 # 以非守护(foreground)方式启动 nginx,使容器持续运行 CMD ["nginx", "-g", "daemon off;"]

进入exercise1目录,构建镜像并运行容器:

➜ /workspace git:(main) cd exercise1 ➜ exercise1 git:(main) docker build -t exercise1 .

➜ exercise1 git:(main) docker run -d -p 8080:80 exercise1

使用curl测试容器中的网站:

➜ exercise1 git:(main) curl http://127.0.0.1:8080 | grep -q "Hello Docker"

如果命令执行无输出,表示网页内容包含"Hello Docker!",测试通过。

练习 2:Python 应用构建

  • 使用python:3.11-slim作为基础镜像

  • 安装应用依赖并创建非 root 用户运行应用

  • 设置工作目录并复制应用代码

  • 设置环境变量(例如禁用字节码生成、指定应用端口等)

  • 暴露应用端口并启动服务

编写Dockerfile

# 1. 使用 python:3.11-slim 作为基础镜像 FROM python:3.11-slim # 2. 设置环境变量 ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ APP_PORT=5000 # 3. 创建非 root 用户 RUN adduser --disabled-password --gecos "" appuser # 4. 设置工作目录 WORKDIR /app # 5. 先复制依赖文件(利用 Docker 缓存) COPY requirements.txt . # 6. 安装依赖 RUN pip install --no-cache-dir -r requirements.txt # 7. 复制应用代码 COPY app.py . # 8. 修改文件权限(确保非 root 用户可访问) RUN chown -R appuser:appuser /app # 9. 切换到非 root 用户 USER appuser # 10. 暴露端口 EXPOSE 5000 # 11. 启动应用 CMD ["python", "app.py"]

应用代码app.py如下:

from flask import Flask, jsonify import os app = Flask(__name__) @app.route('/') def hello(): return jsonify({ 'message': 'Hello Docker!', 'status': 'success' }) @app.route('/health') def health(): return jsonify({ 'status': 'healthy', 'version': '1.0.0' }) if __name__ == '__main__': port = int(os.environ.get('PORT', 5000)) app.run(host='0.0.0.0', port=port)

依赖文件requirements.txt包含:

Flask==3.0.0 Werkzeug==3.0.1 click==8.1.7 itsdangerous==2.1.2 Jinja2==3.1.2 MarkupSafe==2.1.3

进入exercise2目录,构建镜像并运行容器:

➜ /workspace git:(main) cd exercise2 ➜ exercise2 git:(main) docker build -t exercise2 .

使用浏览器或curl访问http://localhost:5000/,应返回如下 JSON 响应:

➜ exercise2 git:(main) docker run -d -p 5000:5000 exercise2

命令行界面测试镜像

练习 3:Rust 多阶段构建

  • 使用多阶段构建优化 Rust 应用的 Docker 镜像。

第一阶段(Builder 阶段):

  • 使用rust:1.75-slim作为基础镜像

  • 设置工作目录

  • 安装musl-tools并添加x86_64-unknown-linux-musl目标以支持静态链接

  • 复制Cargo.tomlCargo.lock(如果存在)及所有源代码

  • 使用cargo build --release --target x86_64-unknown-linux-musl构建应用

第二阶段(Runtime 阶段):

  • 使用alpine:latest作为基础镜像

  • 安装运行时依赖(如tzdata

  • 从第一阶段复制编译好的二进制文件

  • 设置工作目录并运行应用

Dockerfile文件内容:

# ========================= # Builder # ========================= FROM rust:1.75-slim AS builder WORKDIR /app RUN apt-get update \ && apt-get install -y --no-install-recommends musl-tools \ && rm -rf /var/lib/apt/lists/* RUN rustup target add x86_64-unknown-linux-musl # 直接复制全部源码(不做任何缓存优化) COPY . . # 构建(明确、直接、无歧义) RUN cargo build --release --target x86_64-unknown-linux-musl # 打印产物,作为铁证 RUN echo "=== BUILT FILES ===" \ && ls -lh target/x86_64-unknown-linux-musl/release # ========================= # Runtime # ========================= FROM alpine:latest RUN apk add --no-cache tzdata WORKDIR /app # ⚠️ 这里的 hello-rust 必须等于 Cargo.toml 的 package.name COPY --from=builder /app/target/x86_64-unknown-linux-musl/release/rust-docker-example ./app CMD ["./app"]

项目文件结构包括Cargo.toml

[package] name = "rust-docker-example" version = "0.1.0" edition = "2021" [dependencies] chrono = "0.4"

以及应用源代码main.rs

use chrono::Local; fn main() { // 获取当前时间 let now = Local::now(); let timestamp = now.format("%Y-%m-%d %H:%M:%S").to_string(); // 直接输出到 stdout println!("Hello from Rust!"); println!("当前时间: {}", timestamp); }

进入exercise3目录,构建镜像并运行容器验证:

➜ /workspace git:(main) cd exercise3 ➜ exercise3 git:(main) docker build -t rust-exercise3 .

➜ exercise3 git:(main) docker run rust-exercise3

可看到输出"Hello fromRust!"及当前时间戳,表示镜像构建成功。

基础部分提交查看分数

随后我们利用git相关命令进行提交

git add . git commit -m "feat: ***" git push

提交之后我们就可以前往相关地方查看我们上面这三个题目一共得分多少,下面的截图中可以很清晰的看到,我们上述的基础题作答是没有问题的。

专业练习

练习 1: Docker 存储管理与 Volume 持久化

  • 使用 Docker Volume 持久化 MySQL 数据,确保容器重启后数据不丢失

  • 通过init.sql初始化脚本创建testdb数据库

  • 使用环境变量设置 MySQLroot密码

  • 提供测试脚本验证数据持久化

  • 使用 Docker Compose 部署

docker-compose.yml文件内容:

version: '3.8' # 在这里编写你的 docker-compose.yml 文件 services: mysql: image: mysql:8.0 container_name: mysql-db restart: unless-stopped environment: # 通过环境变量设置 root 密码(作业要求) MYSQL_ROOT_PASSWORD: "123456" ports: - "3306:3306" # 将 MySQL 暴露到主机 3306 volumes: - mysql-data:/var/lib/mysql # named volume,持久化 MySQL 数据目录 - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # 首次启动自动执行 volumes: mysql-data:

初始化脚本init.sql

CREATE DATABASE IF NOT EXISTS testdb; USE `testdb`; CREATE TABLE IF NOT EXISTS sample ( id INT AUTO_INCREMENT PRIMARY KEY, msg VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); INSERT INTO sample (msg) VALUES ('Hello, persistent world');

启动服务并测试数据持久化:

docker compose up -d docker compose exec mysql mysql -uroot -p123456 -e "SHOW DATABASES;"

执行后可看到testdb数据库存在,说明通过初始化脚本创建的数据库和表已生效,并且数据已保存在卷中。

练习 2:Docker 网络管理与自定义 Bridge

  • 构建一个支持 Redis 计数功能的 Python Web 应用镜像。

  • 选择合适的 Python 基础镜像并安装flaskredis等依赖。

  • 将应用代码拷贝到镜像中并暴露相应端口。

  • 配置容器的启动命令。

Dockerfile

FROM python:3.10-slim # 在这里编写你的 Dockerfile # 设置工作目录 WORKDIR /app # 复制依赖文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码 COPY app.py . # 暴露端口 EXPOSE 5000 # 容器启动命令 CMD ["python", "app.py"]

应用代码app.py

from flask import Flask import redis app = Flask(__name__) r = redis.Redis(host='redis', port=6379, decode_responses=True) @app.route('/ping') def ping(): count = r.incr('count') return f'PONG {count}\n', 200 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)

requirements.txt内容:

version: '3.8' # 在这里编写你的 docker-compose.yml 文件 services: redis: image: redis:7 container_name: redis networks: - mynet web: build: . container_name: web ports: - "5000:5000" depends_on: - redis networks: - mynet networks: mynet: driver: bridge

docker-compose.yml

➜ exercise2 git:(main) docker compose up -d

启动服务并测试:

➜ exercise2 git:(main) docker compose up -d

使用curl访问http://localhost:5000/ping,每次请求会返回带有递增计数的PONG响应,例如:

➜ exercise2 git:(main) curl http://localhost:5000/ping

练习 3:Docker Compose 多容器编排

  • 使用 Docker Compose 编排 Golang Web 服务、MySQL 和 Nginx 三个服务。

  • Golang Web 服务实现/count路径,计数值存储在 MySQL 数据库中。

  • 使用 Nginx 反向代理,将主机的 8080 端口转发到 Golang 服务的 5000 端口。

  • 各服务通过自定义网络app-network互联,Web 服务仅对 Nginx 暴露接口。

  • 提供测试脚本验证计数功能。

Golang 应用

应用目录./app下的Dockerfile

FROM golang:1.21-alpine AS builder # 在这里编写你的 Dockerfile WORKDIR /app # 先复制依赖描述文件 COPY go.mod go.sum ./ RUN go mod download # 再复制源码 COPY main.go ./ RUN go build -o app EXPOSE 5000 CMD ["./app"]

Go 模块文件go.mod

module counter-app go 1.21 require github.com/go-sql-driver/mysql v1.7.1

./app/go.sum

github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=

源代码main.go

package main import ( "database/sql" "fmt" "log" "net/http" "os" "time" _ "github.com/go-sql-driver/mysql" ) var db *sql.DB func main() { dsn := os.Getenv("MYSQL_DSN") if dsn == "" { dsn = "root:123456@tcp(mysql:3306)/counter" } var err error // 等待 MySQL 启动 for i := 0; i < 10; i++ { db, err = sql.Open("mysql", dsn) if err == nil && db.Ping() == nil { break } time.Sleep(2 * time.Second) } if err != nil { log.Fatal("数据库连接失败:", err) } _, _ = db.Exec(`CREATE TABLE IF NOT EXISTS counter (id INT PRIMARY KEY, value INT)`) _, _ = db.Exec(`INSERT IGNORE INTO counter (id, value) VALUES (1, 0)`) http.HandleFunc("/count", countHandler) fmt.Println("Server running on :5000") log.Fatal(http.ListenAndServe(":5000", nil)) } func countHandler(w http.ResponseWriter, r *http.Request) { _, _ = db.Exec(`UPDATE counter SET value = value + 1 WHERE id = 1`) var value int _ = db.QueryRow(`SELECT value FROM counter WHERE id = 1`).Scan(&value) fmt.Fprintf(w, "Count: %d\n", value) }

Nginx 配置文件./nginx/nginx.conf

events {} http { server { listen 8080; location / { proxy_pass http://app:5000; } } }

docker-compose.yml文件:

version: '3.8' # 在这里编写你的 docker-compose.yml 文件 services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: 123456 MYSQL_DATABASE: testdb volumes: - mysql-data:/var/lib/mysql networks: - app-network app: build: ./app environment: MYSQL_DSN: root:123456@tcp(mysql:3306)/testdb depends_on: - mysql networks: - app-network nginx: image: nginx:1.25 ports: - "8080:8080" volumes: - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro depends_on: - app networks: - app-network volumes: mysql-data: networks: app-network: driver: bridge

启动并构建服务:

docker compose up -d --build

测试计数功能:

➜ exercise3 git:(main) curl http://localhost:8080/count

每次访问会返回递增的计数值

专业部分提交查看分数

随后我们利用git相关命令进行提交

git add . git commit -m "feat: ***" git push

提交之后我们就可以前往相关地方查看我们上面这三个题目得分多少,下面的截图中可以很清晰的看到,我们上述的基础题作答是没有问题的。

总结

基础练习 重点夯实容器化的基本功:

  1. 基础镜像与命令:以Ubuntu为基础,演示了镜像定制、软件包安装、文件复制、端口暴露和前台进程启动的完整流程。

  2. Python应用构建:展示了如何在镜像中创建非root用户、管理Python依赖、设置环境变量,并以Flask应用为例实现了安全、可配置的容器化部署。

  3. Rust多阶段构建:利用多阶段构建大幅优化镜像体积,结合musl工具链实现静态编译,最终在极简的Alpine镜像中运行,体现了生产级镜像的优化思路。

专业练习 深入实际生产场景中的复杂需求:

  1. 存储管理与数据持久化:通过Docker Volume实现MySQL数据的持久化存储,并结合docker-compose与服务初始化脚本,确保数据库服务的状态与数据在容器生命周期之外得以保留。

  2. 网络管理与服务通信:基于自定义Bridge网络,构建了Python Web应用与Redis缓存服务的通信架构,演示了服务发现、内部网络隔离与端口映射的配置方法。

  3. 多容器编排实战:综合运用Golang、MySQL与Nginx,通过Docker Compose实现了完整的应用编排。涵盖了服务依赖管理、环境变量注入、反向代理配置以及自定义网络隔离,完整模拟了一个典型Web应用的后端架构。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/21 14:44:03

GHelper完全攻略:华硕笔记本硬件控制与性能优化终极指南

GHelper完全攻略&#xff1a;华硕笔记本硬件控制与性能优化终极指南 【免费下载链接】g-helper Lightweight Armoury Crate alternative for Asus laptops. Control tool for ROG Zephyrus G14, G15, G16, M16, Flow X13, Flow X16, TUF, Strix, Scar and other models 项目地…

作者头像 李华
网站建设 2026/8/21 1:22:03

B站视频下载神器:BiliDownloader全方位使用指南

还在为无法离线观看B站优质内容而烦恼吗&#xff1f;今天为大家介绍一款界面精简、操作简单且高速下载的B站视频下载工具——BiliDownloader&#xff01;无论你是想收藏UP主的精彩作品&#xff0c;还是需要离线学习教学视频&#xff0c;这款神器都能帮你轻松搞定&#xff01; 【…

作者头像 李华
网站建设 2026/8/21 5:00:41

12、SIFTpack:高效SIFT匹配的紧凑表示

SIFTpack:高效SIFT匹配的紧凑表示 在计算机视觉领域,SIFT(尺度不变特征变换)描述符的匹配和存储是重要的研究方向。传统方法在处理大规模SIFT描述符时,存在时间和空间效率低下的问题。本文将介绍一种名为SIFTpack的紧凑表示方法,它能够显著提高SIFT匹配的效率。 1. 图像…

作者头像 李华
网站建设 2026/8/21 22:21:50

Python小型家政服务管理系统的实现与设计_eb0c0cla

目录已开发项目效果实现截图关于我系统介绍开发技术路线核心代码参考示例本项目开发思路结论源码lw获取/同行可拿货,招校园代理 &#xff1a;文章底部获取博主联系方式&#xff01;已开发项目效果实现截图 同行可拿货,招校园代理 Python小型家政服务管理系统的实现与设计_eb…

作者头像 李华
网站建设 2026/8/21 11:49:52

18、基于非参数采样的视频深度提取技术解析

基于非参数采样的视频深度提取技术解析 在计算机视觉领域,从视频中提取深度信息并将2D视频转换为3D视频是一个重要的研究方向。本文将详细介绍一种基于非参数采样的深度提取方法,该方法能够有效地从视频中提取深度信息,并实现更准确、时间连贯的深度估计。 1. 相关工作对比…

作者头像 李华