进阶 getfoundry.sh 2026-10-10 09:32:10 · 6 阅读

第3章 Docker 与容器化部署 Foundry

Docker 与容器

本指南介绍如何在 Docker 中运行 Foundry,以实现可复现的构建、CI 流水线和隔离的开发环境。

官方 Foundry Docker 镜像

从 GitHub Container Registry 拉取官方 Foundry 镜像:

$ docker pull ghcr.io/foundry-rs/foundry:latest

可用标签:

标签说明
latest最新稳定版本
nightly每夜构建版
v1.0.0指定版本

使用 Podman

官方 Foundry 容器镜像兼容 OCI,也可以配合 Podman 使用。

拉取镜像:

$ podman pull ghcr.io/foundry-rs/foundry:latest

下文提到的 Docker 命令都可以用 Podman 运行,只需把 docker 替换为 podman。例如:

# 用 Podman 运行 forge build
$ podman run --rm -v $(pwd):/app -w /app --entrypoint forge ghcr.io/foundry-rs/foundry build

注意

在某些 rootless Podman 配置下,需要写入 bind 挂载目录的命令(如 forge init)可能需要额外的 user namespace 配置(例如 --userns=keep-id)来避免权限问题。

运行 Foundry 命令

镜像默认以 /bin/sh -c 作为 entrypoint。可以通过 --entrypoint 指定 Foundry 可执行文件,让镜像名后面的参数传给它:

# 运行 forge build
$ docker run --rm -v $(pwd):/app -w /app --entrypoint forge ghcr.io/foundry-rs/foundry build

# 运行测试
$ docker run --rm -v $(pwd):/app -w /app --entrypoint forge ghcr.io/foundry-rs/foundry test

# 运行 cast
$ docker run --rm --entrypoint cast ghcr.io/foundry-rs/foundry block-number --rpc-url https://ethereum.reth.rs/rpc

也可以保留默认 entrypoint,把整条命令作为一个参数传入:

$ docker run --rm ghcr.io/foundry-rs/foundry "cast wallet new-mnemonic"

方便起见的 shell 别名

在 shell 配置文件中添加:

~/.bashrc$ alias dforge='docker run --rm -v $(pwd):/app -w /app --entrypoint forge ghcr.io/foundry-rs/foundry'
$ alias dcast='docker run --rm --entrypoint cast ghcr.io/foundry-rs/foundry'
$ alias danvil='docker run --rm -p 8545:8545 --entrypoint anvil ghcr.io/foundry-rs/foundry --host 0.0.0.0'

然后就可以这样使用:

$ dforge build
$ dforge test
$ dcast balance 0x1234...

自定义 Dockerfile

创建包含项目依赖的项目专属镜像:

DockerfileFROM ghcr.io/foundry-rs/foundry:latest

WORKDIR /app

# 先复制依赖清单以便利用缓存
COPY foundry.toml .
COPY remappings.txt .

# 安装 git 用于管理依赖
RUN apk add --no-cache git

# 复制源码文件
COPY src ./src
COPY test ./test
COPY script ./script
COPY lib ./lib

# 构建项目
RUN forge build

# 默认命令
ENTRYPOINT ["forge"]
CMD ["test"]

构建并运行:

$ docker build -t my-project .
$ docker run --rm my-project
$ docker run --rm my-project test -vvv

Docker Compose 配置

适合需要在测试的同时运行 Anvil 的项目:

docker-compose.ymlservices:
  anvil:
    image: ghcr.io/foundry-rs/foundry:latest
    entrypoint: ["anvil"]
    command: ["--host", "0.0.0.0"]
    ports:
      - "8545:8545"
    healthcheck:
      test: ["CMD", "cast", "block-number", "--rpc-url", "http://localhost:8545"]
      interval: 2s
      timeout: 5s
      retries: 10

  test:
    image: ghcr.io/foundry-rs/foundry:latest
    entrypoint: ["forge"]
    volumes:
      - .:/app
    working_dir: /app
    depends_on:
      anvil:
        condition: service_healthy
    command: ["test", "--fork-url", "http://anvil:8545"]

  deploy:
    image: ghcr.io/foundry-rs/foundry:latest
    entrypoint: ["forge"]
    volumes:
      - .:/app
    working_dir: /app
    depends_on:
      anvil:
        condition: service_healthy
    command: script script/Deploy.s.sol --broadcast --rpc-url http://anvil:8545 --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

运行测试:

$ docker compose up test

部署到本地 Anvil:

$ docker compose up deploy

GitHub Actions CI

.github/workflows/test.ymlname: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Install Foundry
        uses: foundry-rs/foundry-toolchain@v1

      - name: Build
        run: forge build

      - name: Test
        run: forge test -vvv

      - name: Check formatting
        run: forge fmt --check

      - name: Gas snapshot
        run: forge snapshot --check --tolerance 5

基于 Docker 的 CI 运行器

适合自托管 runner 或没有 foundry-toolchain 的环境:

.github/workflows/test.ymlname: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/foundry-rs/foundry:latest
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Build
        run: forge build

      - name: Test
        run: forge test -vvv

可复现构建

固定 Foundry 版本以实现可复现构建:

DockerfileFROM ghcr.io/foundry-rs/foundry:v1.0.0

# ... 其余 Dockerfile 内容

或在 CI 中:

.github/workflows/test.yml- name: Install Foundry
  uses: foundry-rs/foundry-toolchain@v1
  with:
    version: v1.0.0

在 Docker 中运行 Anvil

把 Anvil 暴露给宿主机:

$ docker run --rm -p 8545:8545 --entrypoint anvil ghcr.io/foundry-rs/foundry --host 0.0.0.0

Anvil 必须绑定 0.0.0.0(而不是 127.0.0.1),才能从容器外部访问。

持久化状态:

$ docker run --rm -p 8545:8545 -v anvil-state:/state --entrypoint anvil ghcr.io/foundry-rs/foundry \
    --host 0.0.0.0 --state /state/anvil.json

多阶段构建

使用多阶段构建优化镜像体积:

Dockerfile# 构建阶段
FROM ghcr.io/foundry-rs/foundry:latest AS builder

WORKDIR /app
COPY . .
RUN forge build --optimize

# 运行阶段
FROM ghcr.io/foundry-rs/foundry:latest AS runtime

WORKDIR /app
COPY --from=builder /app/out ./out
COPY --from=builder /app/broadcast ./broadcast

# 只保留部署所需的内容
ENTRYPOINT ["forge"]
CMD ["script", "script/Deploy.s.sol", "--broadcast"]

环境变量

传入密钥和配置:

$ docker run --rm \
    -v $(pwd):/app \
    -w /app \
    -e PRIVATE_KEY \
    -e ETHERSCAN_API_KEY \
    --entrypoint forge \
    ghcr.io/foundry-rs/foundry \
    script script/Deploy.s.sol --broadcast --verify

或通过 env 文件:

$ docker run --rm \
    -v $(pwd):/app \
    -w /app \
    --env-file .env \
    --entrypoint forge \
    ghcr.io/foundry-rs/foundry \
    script script/Deploy.s.sol --broadcast

最佳实践

实践说明
固定版本使用具体标签而非 latest,保证可复现性
缓存依赖先复制依赖清单再复制源码,充分利用层缓存
多阶段构建排除构建产物,减小最终镜像体积
合理挂载本地开发用 -v,CI 中用 COPY
正确暴露端口容器中的 Anvil 需使用 --host 0.0.0.0

这篇文档有帮助吗?在 GitHub 上提交修改建议

评论 (0)