Skip to content

Docker

Docker 是一个开源的容器化平台,用于自动化应用程序的部署、扩展和管理。

Overview

Docker 通过容器技术,将应用及其依赖打包成标准化的单元,实现"一次构建,到处运行"。

核心概念

  • 镜像(Image) - 只读的应用模板
  • 容器(Container) - 镜像的运行实例
  • Dockerfile - 构建镜像的脚本
  • Docker Compose - 多容器应用编排工具

容器生命周期与前台运行

1. 核心原理:容器 ≠ 虚拟机

Docker 容器的本质是宿主机上的一个进程,不是虚拟机。Docker 通过监控容器的 主进程(PID 1) 来管理容器的生命周期:

┌─────────────────────────────────────┐
│  宿主机                              │
│                                     │
│  ┌───────────────────────────────┐  │
│  │  Docker 容器                   │  │
│  │                               │  │
│  │  PID 1: nginx (主进程) ← 监控  │  │
│  │    ├─ worker process 1        │  │
│  │    ├─ worker process 2        │  │
│  │    └─ worker process 3        │  │
│  │                               │  │
│  │  规则:主进程退出 = 容器停止    │  │
│  └───────────────────────────────┘  │
│                                     │
└─────────────────────────────────────┘

生命周期规则:

  • 主进程存活 → 容器运行 ✅
  • 主进程退出 → 容器停止 ❌

2. 为什么需要前台运行?

以 Nginx 为例,对比两种运行模式:

后台模式(Daemon,默认)

传统 Linux 服务器上,Nginx 以守护进程方式运行:

bash
# 在普通服务器上
$ nginx                    # 启动 Nginx
$ echo $?                  # 主进程立即退出,返回 0
0
$ ps aux | grep nginx      # Nginx 在后台运行
root     123  nginx: master process
nginx    124  nginx: worker process

工作流程:

  1. 执行 nginx 命令
  2. 主进程 fork 出 master 和 worker 进程
  3. 主进程立即退出(返回到 shell)
  4. Master 和 worker 进程在后台持续运行

这种模式在普通服务器上没问题,但在 Docker 容器中:

dockerfile
FROM nginx:alpine
CMD ["nginx"]  # ❌ 容器会立即退出
bash
$ docker run -d nginx:alpine nginx
$ docker ps                # 容器已停止,查不到
$ docker ps -a             # 查看已停止的容器
CONTAINER ID   STATUS
abc123         Exited (0) 1 second ago

为什么容器退出?

  • Docker 只监控主进程(PID 1)
  • nginx 命令启动后主进程立即退出
  • Docker 检测到主进程退出 → 认为任务完成 → 停止容器

前台模式(Foreground,daemon off)

让 Nginx 以前台进程运行:

dockerfile
FROM nginx:alpine
# ✅ 使用 daemon off 让主进程持续运行
CMD ["nginx", "-g", "daemon off;"]
bash
$ docker run -d nginx:alpine nginx -g "daemon off;"
$ docker ps                # 容器正常运行
CONTAINER ID   STATUS
abc123         Up 5 seconds

工作流程:

  1. 执行 nginx -g "daemon off;" 命令
  2. Nginx 以前台模式启动
  3. 主进程持续运行(不退出)
  4. Docker 检测到主进程存活 → 容器保持运行

3. 其他服务的前台运行

所有容器化的服务都需要以前台模式运行:

PostgreSQL(Jungle 项目实例)

yaml
# docker-compose.dev.yml
services:
  postgres_dev:
    container_name: jungle_postgres_dev
    image: postgres:17-alpine
    ports:
      - '5432:5432'
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=mysecretpassword
      - POSTGRES_DB=jungle

PostgreSQL 官方镜像的默认启动命令:

dockerfile
# postgres:17-alpine 镜像内部
CMD ["postgres"]  # ✅ postgres 进程本身就是前台运行

说明:

  • PostgreSQL 的 postgres 命令默认以前台模式运行
  • 与 MySQL 的 mysqld 命令类似,都是前台进程
  • 不需要额外配置,直接使用官方镜像即可

Redis(Jungle 项目实例)

yaml
# docker-compose.dev.yml
services:
  redis_dev:
    container_name: jungle_redis_dev
    image: redis:7-alpine
    ports:
      - '6379:6379'
    volumes:
      - redis_data:/data

Redis 官方镜像的默认启动命令:

dockerfile
# redis:7-alpine 镜像内部
CMD ["redis-server"]  # ✅ 默认前台运行(--daemonize no)

说明:

  • Redis 官方镜像已经配置为前台运行模式
  • 默认禁用了 daemonize 选项(daemonize no
  • 直接使用官方镜像即可

Node.js 应用(Jungle 项目实例)

dockerfile
# Dockerfile.dev
FROM node:20-alpine

WORKDIR /app

RUN npm install -g pnpm

COPY package.json pnpm-lock.yaml ./
RUN pnpm install

COPY . .

# NestJS 开发模式
CMD ["pnpm", "start:dev"]  # ✅ Node 进程持续运行

说明:

  • Node.js 应用(Express、NestJS、Koa 等)默认都是前台运行
  • node server.jspnpm start:dev 启动的进程会持续运行
  • 应用监听端口,等待请求,主进程不会退出

自定义脚本

如果需要运行 shell 脚本作为主进程:

dockerfile
FROM alpine
COPY start.sh /start.sh
# 使用 exec 确保脚本中的进程成为 PID 1
CMD ["sh", "-c", "exec /start.sh"]

4. 验证主进程

进入容器查看 PID 1:

bash
# 进入容器
docker exec -it bush_app sh

# 查看进程树
ps aux
# PID   USER     COMMAND
# 1     root     nginx: master process nginx -g daemon off;
# 7     nginx    nginx: worker process
# 8     nginx    nginx: worker process

# 验证 PID 1 是 nginx 主进程
cat /proc/1/cmdline
# nginx-gdaemon off;

5. 实战建议

  1. 使用官方镜像 - 官方镜像已经配置好前台运行模式

    dockerfile
    FROM nginx:alpine       # 已配置 daemon off
    FROM redis:alpine       # 已配置 daemonize no
    FROM postgres:17-alpine # 已配置 foreground mode
  2. 自定义服务 - 确保主进程不退出

    dockerfile
    # ❌ 错误:脚本执行完就退出
    CMD ["sh", "-c", "echo 'Starting...' && exit 0"]
    
    # ✅ 正确:主进程持续运行
    CMD ["sh", "-c", "echo 'Starting...' && tail -f /dev/null"]
  3. 调试容器退出问题

    bash
    # 查看容器退出状态
    docker ps -a
    
    # 查看容器日志
    docker logs container_name
    
    # 查看容器退出码
    docker inspect container_name | grep ExitCode

实战案例:Bush & Jungle 容器化实践

本节以真实项目 Bush(React 前端)和 Jungle(NestJS 后端)为例,展示完整的容器化开发和部署方案。

项目架构

开发环境(完全容器化)

┌──────────────────────────────────────────────────────────────────────┐
│  Docker 网络:jungle_default(默认桥接网络)                          │
│                                                                      │
│  ┌────────────────────────┐                                         │
│  │  Bush 容器              │                                         │
│  │  bush_app_dev          │                                         │
│  │  ─────────────────────  │                                         │
│  │  镜像: node:20-alpine   │                                         │
│  │  端口: 8000 → 8000      │  ← 浏览器访问 localhost:8000           │
│  │  服务: UmiJS Dev Server │                                         │
│  │  特性: HMR 热更新       │                                         │
│  │                        │                                         │
│  │  Proxy 配置:           │                                         │
│  │  /api/* → jungle_app_dev:3000                                    │
│  └────────────┬───────────┘                                         │
│               │ HTTP 请求                                           │
│               │                                                     │
│  ┌────────────▼───────────┐                                         │
│  │  Jungle 容器            │                                         │
│  │  jungle_app_dev        │                                         │
│  │  ─────────────────────  │                                         │
│  │  镜像: node:20-alpine   │                                         │
│  │  端口: 3000 → 3000      │                                         │
│  │  服务: NestJS API       │                                         │
│  │  特性: 热重载           │                                         │
│  │                        │                                         │
│  │  依赖健康检查:          │                                         │
│  │  - PostgreSQL Ready     │                                         │
│  │  - Redis Ready          │                                         │
│  └───┬──────────────┬─────┘                                         │
│      │              │                                               │
│      │ TypeORM      │ Redis Client                                  │
│      │              │                                               │
│  ┌───▼────────┐  ┌──▼─────────┐                                    │
│  │ PostgreSQL │  │ Redis      │                                    │
│  │ 容器       │  │ 容器       │                                    │
│  │ ────────── │  │ ────────── │                                    │
│  │ postgres_dev│  │ redis_dev  │                                    │
│  │            │  │            │                                    │
│  │ 镜像:      │  │ 镜像:      │                                    │
│  │ postgres:  │  │ redis:     │                                    │
│  │ 17-alpine  │  │ 7-alpine   │                                    │
│  │            │  │            │                                    │
│  │ 端口:      │  │ 端口:      │                                    │
│  │ 5432→5432  │  │ 6379→6379  │                                    │
│  │            │  │            │                                    │
│  │ 数据持久化: │  │ 数据持久化: │                                    │
│  │ postgres_  │  │ redis_data │                                    │
│  │ data volume│  │ volume     │                                    │
│  │            │  │            │                                    │
│  │ 健康检查:   │  │ 健康检查:   │                                    │
│  │ pg_isready │  │ redis-cli  │                                    │
│  │            │  │ ping       │                                    │
│  └────────────┘  └────────────┘                                    │
│                                                                      │
│  卷(Volumes):                                                      │
│  - bush_node_modules: Bush 依赖缓存                                 │
│  - app_node_modules: Jungle 依赖缓存                                │
│  - postgres_data: 数据库数据持久化                                  │
│  - redis_data: 缓存数据持久化                                       │
└──────────────────────────────────────────────────────────────────────┘

通信流程说明:

  1. 浏览器 → Bush:用户访问 http://localhost:8000
  2. Bush → Jungle:前端通过 UmiJS proxy 将 /api/* 请求转发到 http://jungle_app_dev:3000(容器名解析)
  3. Jungle → PostgreSQL:后端通过 TypeORM 连接数据库(postgres_dev:5432
  4. Jungle → Redis:后端通过 ioredis 连接缓存(redis_dev:6379
  5. 依赖启动顺序:PostgreSQL/Redis 健康检查通过 → Jungle 启动 → Bush 启动

生产环境

┌──────────────────────────────────────────────────────────────────────┐
│  Docker 网络:jungle_default                                          │
│                                                                      │
│  ┌────────────────────────┐                                         │
│  │  Bush 容器              │                                         │
│  │  bush_app              │                                         │
│  │  ─────────────────────  │                                         │
│  │  镜像: nginx:alpine     │                                         │
│  │  端口: 80 → 80          │  ← 客户端访问                          │
│  │  服务: Nginx            │                                         │
│  │                        │                                         │
│  │  功能:                 │                                         │
│  │  1. 静态文件服务        │                                         │
│  │     / → /usr/share/    │                                         │
│  │         nginx/html/    │                                         │
│  │                        │                                         │
│  │  2. API 反向代理        │                                         │
│  │     /api/* → jungle_app:3000                                     │
│  │     (重写: /api/users → /users)                                  │
│  │                        │                                         │
│  │  3. 用户文件服务        │                                         │
│  │     /static/* → 共享目录 │                                         │
│  └────────────┬───────────┘                                         │
│               │ HTTP 请求(反向代理)                                │
│               │                                                     │
│  ┌────────────▼───────────┐                                         │
│  │  Jungle 容器            │                                         │
│  │  jungle_app            │                                         │
│  │  ─────────────────────  │                                         │
│  │  镜像: node:20-alpine   │                                         │
│  │  端口: 3000 (内部)      │                                         │
│  │  服务: NestJS API       │                                         │
│  │  模式: 生产模式         │                                         │
│  └───┬──────────────┬─────┘                                         │
│      │              │                                               │
│      │              │                                               │
│  ┌───▼────────┐  ┌──▼─────────┐                                    │
│  │ PostgreSQL │  │ Redis      │                                    │
│  │ 容器       │  │ 容器       │                                    │
│  │ ────────── │  │ ────────── │                                    │
│  │ jungle_    │  │ jungle_    │                                    │
│  │ postgres   │  │ redis      │                                    │
│  │            │  │            │                                    │
│  │ 端口:      │  │ 端口:      │                                    │
│  │ 5432(内部) │  │ 6379(内部) │                                    │
│  │            │  │            │                                    │
│  │ 数据持久化: │  │ 数据持久化: │                                    │
│  │ 宿主机目录  │  │ 宿主机目录  │                                    │
│  └────────────┘  └────────────┘                                    │
└──────────────────────────────────────────────────────────────────────┘

配置文件详解

1. Jungle 后端配置

docker-compose.dev.yml

yaml
services:
  # 后端应用容器
  app_dev:
    container_name: jungle_app_dev
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - '3000:3000'  # 映射到宿主机,便于调试
    volumes:
      - .:/app                          # 代码实时同步
      - app_node_modules:/app/node_modules  # 依赖隔离
    env_file:
      - .env.development  # 环境变量配置
    depends_on:
      postgres_dev:
        condition: service_healthy  # 等待数据库就绪
      redis_dev:
        condition: service_healthy  # 等待缓存就绪

  # PostgreSQL 数据库容器
  postgres_dev:
    container_name: jungle_postgres_dev
    image: postgres:17-alpine
    ports:
      - '5432:5432'
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=mysecretpassword
      - POSTGRES_DB=jungle
    volumes:
      - postgres_data:/var/lib/postgresql/data  # 数据持久化
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 5s      # 每 5 秒检查一次
      timeout: 5s       # 超时时间
      retries: 10       # 重试 10 次
      start_period: 10s # 启动宽限期

  # Redis 缓存容器
  redis_dev:
    container_name: jungle_redis_dev
    image: redis:7-alpine
    ports:
      - '6379:6379'
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 30

volumes:
  postgres_data:      # 命名卷:数据库数据
  redis_data:         # 命名卷:缓存数据
  app_node_modules:   # 命名卷:依赖缓存

Dockerfile.dev

dockerfile
FROM node:20-alpine

WORKDIR /app

# 安装 pnpm
RUN npm config set registry https://registry.npmmirror.com \
    && npm install -g pnpm \
    && pnpm config set registry https://registry.npmmirror.com

# 复制依赖文件
COPY package.json pnpm-lock.yaml ./

# 安装依赖
RUN pnpm install

# 暴露开发服务器端口
EXPOSE 3000

# 启动 NestJS 开发服务器(热重载)
CMD ["pnpm", "start:dev"]

package.json

json
{
  "scripts": {
    "c:up": "docker compose -f docker-compose.dev.yml up --build",
    "c:down": "docker compose -f docker-compose.dev.yml down -v",
    "start:dev": "NODE_ENV=development nest start --watch"
  }
}

2. Bush 前端配置

docker-compose.dev.yml

yaml
version: '3.8'

services:
  bush_dev:
    container_name: bush_app_dev
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - '8000:8000'
    volumes:
      - .:/app  # 代码实时同步
      - bush_node_modules:/app/node_modules  # 依赖隔离
    environment:
      - REACT_APP_ENV=dev
      - NODE_ENV=development
    networks:
      - jungle_default  # 加入后端网络,可以访问 jungle_app_dev

volumes:
  bush_node_modules:

networks:
  jungle_default:
    external: true  # 使用外部网络(由 Jungle 创建)

Dockerfile.dev

dockerfile
FROM node:20-alpine

WORKDIR /app

# 安装 pnpm
RUN npm config set registry https://registry.npmmirror.com \
    && npm install -g pnpm \
    && pnpm config set registry https://registry.npmmirror.com

# 复制依赖文件
COPY package.json pnpm-lock.yaml ./

# 安装依赖
RUN pnpm install

# 暴露开发服务器端口
EXPOSE 8000

# 启动 UmiJS 开发服务器(HMR)
CMD ["pnpm", "start:dev"]

config/proxy.ts(UmiJS 开发代理)

typescript
export default {
  dev: {
    '/api/': {
      // 通过容器名访问后端(Docker DNS 解析)
      target: 'http://jungle_app_dev:3000',
      changeOrigin: true,
      pathRewrite: { '^/api': '' },  // /api/users → /users
    },
  },
};

package.json

json
{
  "scripts": {
    "dev": "pnpm c:up",
    "c:up": "docker compose -f docker-compose.dev.yml up --build",
    "c:down": "docker compose -f docker-compose.dev.yml down -v",
    "start:dev": "cross-env REACT_APP_ENV=dev MOCK=none UMI_ENV=dev max dev"
  }
}

3. 生产环境配置

Bush Dockerfile(多阶段构建)

dockerfile
# ========================================
# 第一阶段:构建阶段
# ========================================
FROM node:20-alpine AS builder

WORKDIR /app

# 安装 pnpm
RUN npm config set registry https://registry.npmmirror.com \
    && npm install -g pnpm \
    && pnpm config set registry https://registry.npmmirror.com

# 复制依赖文件
COPY package.json pnpm-lock.yaml ./

# 安装依赖
RUN pnpm install --frozen-lockfile

# 复制源代码
COPY . .

# 构建生产版本(在容器内构建,确保环境一致)
RUN pnpm run build

# ========================================
# 第二阶段:生产阶段
# ========================================
FROM nginx:alpine

# 从构建阶段复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html/

# 复制 Nginx 配置文件
COPY nginx.conf /etc/nginx/conf.d/default.conf

# 暴露 80 端口
EXPOSE 80

# 启动 Nginx(前台运行)
CMD ["nginx", "-g", "daemon off;"]

nginx.conf

nginx
server {
    listen 80;
    server_name 1px.club;

    # 前端静态文件
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;  # SPA 路由支持
    }

    # API 反向代理
    location /api/ {
        # Docker 内部 DNS 解析器
        resolver 127.0.0.11 valid=30s;
        set $jungle_service http://jungle_app:3000;
        
        proxy_pass $jungle_service;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # 路径重写:/api/users → /users
        rewrite ^/api/(.*)$ /$1 break;
    }

    # 用户上传文件
    location /static/ {
        alias /app/shared_uploads/;
    }
}

开发流程

启动开发环境

bash
# 1. 启动 Jungle 后端(会自动启动 PostgreSQL 和 Redis)
cd jungle
pnpm c:up

# 查看启动日志,确认健康检查通过
docker compose -f docker-compose.dev.yml logs -f

# 2. 启动 Bush 前端(会自动加入 jungle_default 网络)
cd bush
pnpm dev

# 3. 验证
# - 浏览器访问 http://localhost:8000
# - 前端可以通过 /api/* 访问后端
# - 后端可以访问 PostgreSQL 和 Redis

常用命令

bash
# 查看所有容器状态
docker ps

# 查看网络连接
docker network inspect jungle_default

# 进入容器调试
docker exec -it jungle_app_dev sh
docker exec -it bush_app_dev sh

# 查看容器日志
docker logs -f jungle_app_dev
docker logs -f jungle_postgres_dev

# 停止并清理
cd jungle && pnpm c:down
cd bush && pnpm c:down

生产部署

bash
# 1. 构建镜像(多阶段构建)
cd bush
docker compose build

# 2. 启动服务
docker compose up -d

# 3. 查看状态
docker compose ps

# 4. 查看日志
docker compose logs -f

关键技术点

1. 容器网络通信

开发环境:

  • Bush 通过 external: true 加入 Jungle 创建的 jungle_default 网络
  • 容器间通过容器名互相访问(Docker 内部 DNS)
  • 端口映射到宿主机,便于调试

生产环境:

  • 所有容器在同一 Docker 网络
  • Bush 不映射端口到宿主机(Nginx 监听 80)
  • 数据库和缓存仅内部访问

2. 健康检查与依赖管理

yaml
depends_on:
  postgres_dev:
    condition: service_healthy  # 必须等待健康检查通过

好处:

  • 避免后端启动时数据库未就绪导致连接失败
  • 确保服务启动顺序正确
  • 生产环境更可靠

3. 数据持久化

命名卷(开发环境):

yaml
volumes:
  postgres_data:  # Docker 管理的卷
  redis_data:

绑定挂载(生产环境):

yaml
volumes:
  - /data/postgres:/var/lib/postgresql/data  # 宿主机路径

4. 多阶段构建

优势:

  • 构建环境统一(Node 版本、依赖版本完全一致)
  • 最终镜像小(只包含 Nginx + dist,约 40MB)
  • 安全性高(构建工具不在生产镜像中)
  • 避免"在我机器上能跑"的问题

5. 环境变量管理

开发环境:

yaml
env_file:
  - .env.development  # 开发配置

生产环境:

yaml
environment:
  - NODE_ENV=production
  - DATABASE_URL=${DATABASE_URL}  # 从宿主机传入

性能优化

1. macOS 文件同步优化

yaml
volumes:
  - .:/app:cached  # 添加 cached 标志

2. node_modules 隔离(重要)

问题场景:

如果只挂载代码目录,会导致宿主机和容器的 node_modules 互相覆盖:

yaml
# ❌ 错误示例
volumes:
  - .:/app  # 宿主机的 node_modules 会覆盖容器内的

问题:

宿主机 (macOS/Windows)
├── node_modules/
│   └── esbuild (macOS 二进制)  ❌ 无法在 Linux 容器中运行
└── src/

容器 (Linux Alpine)
├── node_modules/
│   └── esbuild (Linux 二进制)  ✅ 应该使用这个
└── src/
  • 平台不兼容:宿主机(macOS/Windows)的原生模块(esbuild、swc)无法在 Linux 容器中运行
  • 覆盖问题:挂载 .:/app 会把宿主机的 node_modules 覆盖容器内的
  • 启动失败Error: The module was compiled against a different Node.js version

解决方案:单独挂载 node_modules

以 Bush 项目为例:

yaml
# ✅ 正确示例
services:
  bush_dev:
    container_name: bush_app_dev
    volumes:
      # 代码挂载:实时同步代码变更
      - .:/app
      # node_modules 单独挂载:避免宿主机和容器冲突
      - bush_node_modules:/app/node_modules

volumes:
  bush_node_modules:  # Docker 命名卷,存储容器的 node_modules

效果:

宿主机目录
├── node_modules/         (macOS 版本,保留)
├── src/                  ✅ 同步到容器
└── package.json          ✅ 同步到容器

容器内目录
├── node_modules/         (Linux 版本,独立存储在 Docker Volume)
├── src/                  ✅ 从宿主机同步
└── package.json          ✅ 从宿主机同步

优势:

  • 平台隔离:宿主机和容器的 node_modules 完全独立,各自使用匹配平台的二进制
  • 代码同步:代码修改实时同步,热更新正常工作
  • 开发体验:宿主机可以继续使用 VS Code 智能提示(基于本地 node_modules)
  • 启动速度:依赖缓存在 Docker Volume 中,重启容器无需重新安装

验证:

bash
# 进入容器
docker compose -f docker-compose.dev.yml exec bush_dev sh

# 查看 node_modules 位置
ls -la /app/node_modules/.bin/esbuild
# 输出:Linux x86_64 二进制文件

# 在宿主机查看
file node_modules/.bin/esbuild
# 输出:Mach-O 64-bit executable arm64 (macOS)

注意事项:

  • 当更新 package.json 后,需要重新构建容器:docker compose up --build
  • 清理 Volume:docker compose down -v(会删除 node_modules,下次启动重新安装)

3. 镜像加速

dockerfile
RUN npm config set registry https://registry.npmmirror.com

常见问题排查

1. 容器访问不到后端

检查网络:

bash
docker network ls | grep jungle_default
docker network inspect jungle_default

确认容器在同一网络:

bash
docker inspect bush_app_dev | grep NetworkMode
docker inspect jungle_app_dev | grep NetworkMode

2. 数据库连接失败

检查健康状态:

bash
docker ps  # 查看 STATUS 列
docker logs jungle_postgres_dev

手动测试连接:

bash
docker exec -it jungle_postgres_dev psql -U postgres -d jungle

3. 热更新不生效

重新构建容器:

bash
docker compose -f docker-compose.dev.yml down
docker compose -f docker-compose.dev.yml up --build

总结

架构优势:

  • ✅ 环境完全一致(开发/测试/生产)
  • ✅ 快速上手(只需 Docker)
  • ✅ 服务隔离(数据库、缓存、应用)
  • ✅ 易于扩展(添加新服务只需修改 compose 文件)

核心原则:

  • 一次配置,处处运行(Build once, run anywhere)
  • 依赖显式声明(健康检查、启动顺序)
  • 数据持久化(命名卷 vs 绑定挂载)
  • 安全优先(最小化镜像、环境变量管理)

待整理

交互式命令行(进入一个运行中的容器):docker exec -it <container_name> sh

Released under the MIT License.