跳到正文
minimachine.
← 学习路径
第 8 步 · 基础搭建 进阶 · 16 分钟

🐳Docker:隔离您的项目

每个项目都待在自己密封的泡泡里。Docker 防止您的项目互相踩脚,在 agent 做实验时把损失关在盒子里,还让您的部署可复现。新手老手都受用。


您将在这台机器上同时跑好几个项目。一个要 Node 18,另一个要 Node 22。这个需要某个库的老版本,那个要最新版。如果「一锅烩」地装到系统上,它们迟早互相踩脚, 于是您撞上那个经典桥段:「可它之前明明能跑」。Docker 一劳永逸地解决这个问题:每个项目都活在自己密封的泡泡里。

为什么它改变人生(尤其是有了 agent)

三个理由,而第三个被严重低估了:

  • 版本冲突再见。 每个项目自带它确切的环境。这里 Node 18,那里 Node 22,互不干扰。您不再「全局」装任何可能搞坏另一个项目的东西。
  • 可复现的部署。 在您这里跑的容器,跟将来在线上跑的那个一模一样。「在我机器上能跑」消失了:您的机器,就是那个容器。这极大地简化了上线(见 Cloudflare Tunnel)。
  • 损失留在盒子里。 这是和 agent 一起干活时的关键点。一个在做实验的 agent、一个可疑的依赖、一个跑偏的脚本:被关在容器里,它们没法破坏整台机器。这是比「项目文件夹」高一级的隔离, 每个项目一个真正的沙箱(与 保护访问安全 相关联)。

安装 Docker

# 官方方法,一条命令
curl -fsSL https://get.docker.com | sudo sh
# 允许您的用户在不用 sudo 的情况下操控 Docker(之后注销/重新登录)
sudo usermod -aG docker $USER

验证:docker run hello-world 应该下载一个迷你镜像并显示一条欢迎信息。看到它,您就准备好了。

第一级, 跑一个现成的东西(新手)

Docker 起步时最美妙的地方,是您能直接享用别人的成果。成千上万的应用已经「打包入盒」,开箱即用。某个项目需要一个 PostgreSQL 数据库?不用费力安装:

# 一行启动一个隔离的 PostgreSQL 数据库
docker run -d --name ma-db -e POSTGRES_PASSWORD=secret -p 5432:5432 postgres:16
docker ps              # 看看在跑什么
docker logs ma-db      # 看日志
docker stop ma-db      # 停止(docker start ma-db 可重新启动)
docker rm ma-db        # 删除容器(盒子干干净净地消失)

第二级, 一个多服务的小项目(Docker Compose)

大多数项目都由好几块组成:比如一个 app + 一个数据库。Docker Compose 把这一切描述在单个 compose.yml 文件里,再用一条命令把整套都启动起来。

# compose.yml, 一个小型 web app + 它的数据库,一起隔离
services:
  app:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - db-data:/var/lib/postgresql/data   # 数据在重启后存活
volumes:
  db-data:
docker compose up -d      # 全部启动,在后台
docker compose logs -f    # 跟踪发生了什么
docker compose down       # 全部停止并清理

第三级, 打包您自己的项目(Dockerfile)

要把您自己的代码装进盒子,您写一个 Dockerfile:那份说明该如何构建您项目镜像的菜谱。

# Dockerfile, 您盒子的菜谱
FROM node:22-slim          # 从一个官方的、轻量的 Node 镜像出发
WORKDIR /app
COPY package*.json ./
RUN npm ci                  # 在盒子里安装依赖
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]   # 启动 app 的命令
docker build -t mon-app .   # 从 Dockerfile 构建镜像
docker run -d -p 8080:8080 mon-app

从此,您的项目和它的环境合为一体。您可以在任何装了 Docker 的机器上原样启动它。

专家级, 加固隔离

容器已经隔离了不少,但默认情况下它没把篱笆扎到该扎的地方。当您托管一个对外暴露的服务,或者要圈住一个 agent 时,把螺丝拧紧:

  • 不要在容器里以 root 运行 : 在您的 Dockerfile 里加一个非特权用户(USER node)。如果有人从 app 里逃出来,他也不是 root。
  • 只读文件系统 : docker run --read-only 阻止容器往不该写的地方写。
  • 限制资源 : --memory=512m --cpus=1 防止一个失控的容器把整台机器憋死。
  • 削减权限 : --cap-drop=ALL 移除用不上的 Linux capabilities;需要时再一个一个加回来。
  • 隔离网络 : 只发布(-p)真正必要的端口;其余的保持不可见。而您对外发布的东西,要经由 Cloudflare Tunnel 或留在 Tailscale 上,绝不裸奔在互联网上。