Skip to content

开发环境容器化指南 ​

面向团队协作与跨机器一致性,本文记录如何用 Docker 搭建可复用的开发环境,减少“换机器就坏、换同事就不通”的问题。

1. 这篇文档解决什么问题 ​

开发环境容器化,核心不是“把项目部署到线上”,而是把本地开发所依赖的运行时、工具链和辅助服务固定下来。

它主要解决三类问题:

  1. 环境不一致:同一个项目,在 A 电脑能跑,在 B 电脑就缺 Node、缺 Python、缺数据库。
  2. 版本冲突:一个项目要 Node 14,另一个项目要 Node 18,直接装在本机会互相干扰。
  3. 新人接手成本高:新同事拉完代码后,还要手动装一堆软件,常常半天起不来项目。

一句话讲,开发环境容器化做的是:

把“人肉搭环境”变成“拉镜像 + 起容器”。


2. 和运维侧文档的边界 ​

这篇文档只讲开发环境怎么容器化,不展开宿主机 Docker Engine 安装、虚拟化开关、Daemon 配置这些平台问题。

如果你还没把宿主机准备好,请先看:

这两边的分工可以这么理解:

  • 运维侧:Docker 怎么装、宿主机怎么配、镜像怎么拉得快、虚拟化为什么起不来。
  • 开发侧:项目怎么用 Dockerfile 固定工具链、怎么用 Compose 组织多个开发容器、怎么把代码挂进去开始干活。

3. 什么时候值得做开发环境容器化 ​

以下场景最值得做:

  • 团队多人协作,开发机环境经常不一致。
  • 同一台电脑上要并行维护多个项目,运行时版本冲突明显。
  • 项目除了业务代码,还依赖 MySQL、Redis、Node、Python 等外部组件。
  • 经常需要重装系统、换电脑、换同事接手项目。

如果只是一个人维护、依赖极少、生命周期很短的小脚本,就没必要为了“显得高级”强上容器。


4. 推荐的目录结构 ​

建议把开发环境相关文件放在项目根目录下,保证“代码、容器配置、依赖服务”放在一起维护。

text
project-root/
├── .dockerignore
├── docker-compose.yml
├── docker/
│   └── dev/
│       └── Dockerfile
├── app/
│   └── ...                   # 业务代码
├── mysql/
│   └── init/                 # 初始化脚本(按需)
└── README.md

如果只是给某个前端项目做开发容器,也可以更简单:

text
project-root/
├── Dockerfile
├── docker-compose.yml
├── package.json
└── src/

5. Docker 化开发环境的核心思路 ​

5.1 把工具链装进镜像 ​

例如一个前端项目需要:

  • Node.js 14
  • npm 6
  • yarn 1
  • git / curl / vim 等基础工具

那就不要要求每台电脑都手装一遍,而是直接写进 Dockerfile。

5.2 把源码挂载进容器 ​

镜像负责提供运行环境,源码通过 volume 挂载进去。这样你改代码不用重复 build 镜像,容器里能直接看到最新代码。

5.3 用 Compose 管理配套服务 ​

如果开发环境还依赖 MySQL、Redis、MinIO 这类服务,不要靠大家自己装,直接交给 docker-compose.yml 一起起。


6. Dockerfile 示例:前端开发环境 ​

下面是一个偏通用的前端开发环境示例。它的重点不是“极致瘦身”,而是“进入容器后顺手能干活”。

dockerfile
FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive
ARG TZ=Asia/Shanghai
ENV TZ=${TZ}

# 基础工具
RUN apt-get update && apt-get install -y \
    zsh \
    vim \
    wget \
    curl \
    git \
    ca-certificates \
    python3 \
    && rm -rf /var/lib/apt/lists/*

# 设置时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# 创建开发用户
RUN useradd --create-home --shell /bin/bash dev
USER dev
WORKDIR /workspace

# 安装 nvm 与 Node
ENV NVM_DIR=/home/dev/.nvm
ENV NODE_VERSION=14
RUN mkdir -p $NVM_DIR && \
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

RUN bash -lc ". $NVM_DIR/nvm.sh && \
    nvm install ${NODE_VERSION} && \
    nvm use ${NODE_VERSION} && \
    npm install -g yarn"

ENV PATH=/home/dev/.nvm/versions/node/v14.21.3/bin:$PATH

6.1 这个 Dockerfile 的取舍 ​

这类开发环境镜像和生产镜像不一样:

  • 生产镜像优先体积小、攻击面小、启动快。
  • 开发镜像优先工具齐、排障方便、进容器能直接干活。

所以这里选择 Ubuntu 基础镜像是合理的,不必为了省几百 MB 把开发效率搞没了。


7. Compose 示例:项目 + 数据库一起跑 ​

yaml
services:
  app:
    build:
      context: .
      dockerfile: docker/dev/Dockerfile
    container_name: frontend-dev
    working_dir: /workspace
    volumes:
      - ./:/workspace
    ports:
      - "3000:3000"
    tty: true
    command: bash
    depends_on:
      - mysql

  mysql:
    image: mysql:8.0
    container_name: frontend-dev-mysql
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: app_dev
    ports:
      - "33060:3306"
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/init:/docker-entrypoint-initdb.d

7.1 为什么推荐 Compose ​

因为开发环境往往不是单容器问题,而是“一套依赖服务”的问题。

常见组合包括:

  • app + mysql
  • app + redis
  • frontend + api + mysql

docker compose up -d 一把起完,比让每个人手工点点点稳定得多。


8. 日常使用方式 ​

8.1 首次启动 ​

bash
docker compose up -d --build

8.2 进入开发容器 ​

bash
docker compose exec app bash

8.3 在容器里安装依赖并启动项目 ​

bash
yarn install
yarn dev

如果你是 Node 项目,也可以直接:

bash
npm install
npm run dev

9. 常见坑 ​

9.1 容器里有环境,宿主机却没有代码变化 ​

通常是 volume 没挂好,或者工作目录不对。

优先检查:

yaml
volumes:
  - ./:/workspace
working_dir: /workspace

9.2 文件权限混乱 ​

Linux 下常见原因是容器里用户和宿主机用户 UID/GID 不一致,导致生成文件归属异常。

经验做法:

  • 开发环境尽量使用普通用户运行。
  • 真遇到权限问题,再按项目补 user: 或自定义 UID/GID,不要一上来就把所有容器都搞复杂。

9.3 容器之间连不通 ​

在同一个 Compose 网络里,服务之间要用服务名访问,不要写 localhost。

例如:

js
host: 'mysql'

而不是:

js
host: '127.0.0.1'

9.4 开发环境做得太重 ​

有些开发容器把桌面环境、浏览器、各种工具都塞进去,最后 build 一次十几分钟,反而没人愿意用。

判断标准很简单:

只放项目高频需要的依赖,不要把“也许有一天会用到”的工具都塞进去。


10. 实战建议 ​

  1. 先从一个项目试点:不要一上来要求所有项目全部容器化。
  2. 优先容器化依赖复杂的项目:比如前端 + API + MySQL 这种组合,收益最高。
  3. 保留 README 启动命令:让新人只需要看三条命令就能起环境。
  4. 不要把宿主机安装问题写进这篇文档:安装、换源、Daemon 配置统一归运维侧。
  5. 开发镜像与生产镜像分开维护:开发讲求方便,生产讲求稳定,两者不要混成一个 Dockerfile。

11. 一句话总结 ​

开发环境容器化的价值,不是“为了用 Docker 而用 Docker”,而是把团队里最容易反复出问题的环境差异,压缩成一份可以复制、可以启动、可以持续维护的工程资产。

方舟 · Ark