深入学习 Docker:从基础到高级实践

深入学习 Docker:从基础到高级实践

Docker 是现代开发中不可或缺的工具,它通过容器化技术让应用程序的开发、测试和部署更加高效。本文将详细介绍 Docker 的核心概念,并深入探讨如何使用 Dockerfile 和 Docker Compose 构建和管理容器化应用。

Docker 基础知识

Docker 是一个开源平台,用于自动化部署应用程序。它通过容器将应用及其依赖打包在一起,确保在不同环境下的行为一致性。

核心概念详解

  1. 镜像 (Image)
    镜像是一个只读模板,包含操作系统、应用程序代码和依赖。例如,nginx:latest 是一个官方提供的 Nginx 镜像。镜像通过分层文件系统构建,每一层都可以缓存以提高效率。

  2. 容器 (Container)
    容器是镜像的运行时实例。你可以把镜像想象成一张蓝图,而容器是根据蓝图建成的房子。容器是隔离的,但共享宿主机的内核。

  3. Dockerfile
    Dockerfile 是一个脚本文件,定义了如何构建自定义镜像。它包含一系列指令,如 FROMCOPYCMD

  4. Docker Compose
    Docker Compose 是一个工具,用于定义和运行多容器应用。通过一个 YAML 文件,你可以配置多个服务、网络和卷。

安装 Docker

在学习之前,确保已安装 Docker Desktop(Windows/Mac)或 Docker Engine(Linux)。你可以在 Docker 官网 下载安装包。安装完成后,运行以下命令检查版本:

1
2
docker --version
docker-compose --version

如果命令成功输出版本号,说明安装完成。

使用 Dockerfile 构建自定义镜像

Dockerfile 是 Docker 的核心,允许你精确控制镜像的构建过程。让我们以一个 Node.js 应用为例,逐步讲解。

示例 Dockerfile

以下是一个详细的 Dockerfile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 指定基础镜像
FROM node:16-alpine
# alpine 版本更小巧,适合生产环境

# 添加元数据(可选)
LABEL maintainer="Your Name <your.email@example.com>"
LABEL version="1.0"
LABEL description="A simple Node.js app"

# 设置工作目录
WORKDIR /usr/src/app
# 如果目录不存在,Docker 会自动创建

# 复制 package.json 和 package-lock.json(如果有)
COPY package*.json ./
# 使用通配符确保兼容性

# 安装依赖
RUN npm install --production
# --production 跳过 devDependencies,减少镜像体积

# 复制应用代码
COPY src/ ./src/
# 只复制 src 目录,避免不必要的文件

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

# 暴露端口
EXPOSE 3000
# 仅声明端口,实际映射在运行时指定

# 定义容器启动命令
CMD ["node", "src/index.js"]
# CMD 提供默认执行命令,可以在运行时覆盖

构建和运行镜像

  1. 创建一个简单的 Node.js 应用(例如 src/index.js):

    1
    2
    3
    4
    const express = require('express');
    const app = express();
    app.get('/', (req, res) => res.send('Hello Docker!'));
    app.listen(3000, () => console.log('Server running on port 3000'));
  2. 将 Dockerfile 和应用代码放在同一目录下,然后构建镜像:

    1
    docker build -t my-node-app:1.0 .
    • -t 指定镜像名称和标签。
    • . 表示使用当前目录的 Dockerfile。
  3. 运行容器:

    1
    docker run -d -p 3000:3000 --name my-app my-node-app:1.0
    • -d 后台运行。
    • -p 映射宿主机端口到容器端口。
    • --name 指定容器名称。
  4. 访问 http://localhost:3000,你将看到 “Hello Docker!”。

Dockerfile 指令详解

  • FROM:指定基础镜像,必须是第一条非注释指令。
  • WORKDIR:设置工作目录,后续命令在此目录执行。
  • COPY:将本地文件复制到镜像中,支持多层路径。
  • RUN:在构建时执行命令,例如安装依赖。
  • EXPOSE:声明容器监听的端口。
  • CMD:指定容器启动时的默认命令,只能有一条有效。

使用 Docker Compose 管理多容器应用

对于需要多个服务(例如 Web 应用和数据库)的场景,Docker Compose 是理想工具。它通过一个 YAML 文件定义服务、网络和卷。

示例 docker-compose.yml

以下是一个详细的配置文件,包含一个 Node.js 应用和 MongoDB:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
version: '3.8'  # 指定 Compose 文件版本
services:
app: # 服务名称
build:
context: . # 构建上下文(当前目录)
dockerfile: Dockerfile # 指定 Dockerfile
image: my-node-app:1.0 # 自定义镜像名称
ports:
- "3000:3000" # 宿主机:容器端口映射
depends_on:
- db # 依赖 db 服务
environment: # 环境变量
- NODE_ENV=production
- MONGO_URL=mongodb://db:27017/myapp
restart: unless-stopped # 自动重启策略
networks:
- app-network # 自定义网络

db:
image: mongo:5.0 # 使用官方 MongoDB 镜像
ports:
- "27017:27017" # 暴露数据库端口
volumes:
- mongo-data:/data/db # 数据持久化
environment:
- MONGO_INITDB_DATABASE=myapp # 初始化数据库
networks:
- app-network

# 定义卷
volumes:
mongo-data:
driver: local # 使用本地存储

# 定义网络
networks:
app-network:
driver: bridge # 默认桥接网络

修改 Node.js 应用连接 MongoDB

更新 src/index.js

1
2
3
4
5
6
7
8
9
10
const express = require('express');
const mongoose = require('mongoose');
const app = express();

mongoose.connect(process.env.MONGO_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('MongoDB connection error:', err));

app.get('/', (req, res) => res.send('Hello Docker with MongoDB!'));
app.listen(3000, () => console.log('Server running on port 3000'));

确保 package.json 中添加了 mongoose 依赖:

1
npm install mongoose

运行和管理

  1. 在项目根目录运行:

    1
    docker-compose up --build
    • --build 强制重新构建镜像。
  2. 检查运行状态:

    1
    docker-compose ps
  3. 停止并清理:

    1
    docker-compose down --volumes
    • --volumes 删除卷数据。

访问 http://localhost:3000,应用将连接 MongoDB 并运行。

Docker Compose 配置详解

  • services:定义所有服务。
  • build:指定构建镜像的上下文和 Dockerfile。
  • ports:映射端口。
  • depends_on:设置服务启动顺序。
  • volumes:持久化数据。
  • networks:自定义网络隔离。

高级技巧与注意事项

  1. 优化镜像大小

    • 使用 .dockerignore 文件排除不必要的文件(例如 node_modulesgit 等):

      1
      2
      3
      node_modules
      .git
      .gitignore
    • 选择轻量级基础镜像(如 alpine)。

  2. 日志管理
    查看容器日志:

    1
    docker logs my-app
  3. 调试容器
    进入容器内部:

    1
    docker exec -it my-app /bin/sh
  4. 清理资源
    删除未使用的容器、镜像和卷:

    1
    docker system prune

学习资源推荐

  • 官方文档:阅读 Docker DocsCompose Docs
  • 实践项目:尝试容器化一个完整的 Web 应用(前端、后端、数据库)。
  • 视频教程:YouTube 上有许多 Docker 入门课程,例如 TechWorld with Nana 的系列。

总结

通过 Dockerfile,你可以精确控制镜像构建;通过 Docker Compose,你可以轻松管理多服务应用。本文从基础到高级逐步讲解了 Docker 的使用,希望能帮助你快速上手。Docker 的真正力量在于实践,赶快动手试试吧!