はじめに
VS Code の Dev Container を起動しようとしたら、こんなエラーが表示されて途方に暮れた経験はありませんか?
[1461 ms] Error: An error occurred setting up the container.
at c6 (/Users/.../.vscode/extensions/ms-vscode-remote.remote-containers-.../dist/spec-node/devContainersSpecCLI.js:412:4318)
...
[1465 ms] Exit code 1
このエラーメッセージは非常に曖昧で、本当の原因を隠してしまいます。この記事では、実際に遭遇したトラブルの調査過程と解決方法を詳しく解説します。
この記事で学べること
- Dev Container エラーの本当の原因の探り方
- Docker ログを使ったデバッグ手法
- Volume マウントが引き起こす依存関係の問題
- Dockerfile と docker-compose.yml の正しい設定
症状:何が起きたのか
エラーメッセージ
VS Code で「Reopen in Container」を実行したところ、以下のエラーが発生しました。
[1461 ms] Error: An error occurred setting up the container.
[1462 ms] at c6 (/Users/yamato/.vscode/extensions/ms-vscode-remote.remote-containers-...)
[1465 ms] Exit code 1
よくある原因として疑われるもの
Web 検索すると、以下のような原因が挙げられています:
- Docker Desktop が起動していない
- Docker Context が非デフォルト
- Intel Mac での互換性問題
- コンテナの状態が不安定
参考:Dev Container Issues - GitHub
しかし、今回のケースではこれらはすべて該当しませんでした。
調査:本当の原因を探る
Step 1: Docker コンテナの状態を確認
まず、コンテナの状態を確認しました。
docker ps -a
出力:
CONTAINER ID IMAGE COMMAND STATUS
806110879dcb fast-stack-htmx-ai-app "/bin/sh -c 'echo Co…" Restarting (127) 4 seconds ago
1ab066448c96 postgres:16-alpine "docker-entrypoint.s…" Up 4 minutes (healthy)
発見: アプリコンテナが Restarting (127) 状態でした。Exit code 127 は「コマンドが見つからない」を意味します。
Step 2: コンテナログの確認
docker logs mvp-boost-app
出力:
Container started
-: 4: exec: uvicorn: not found
Container started
-: 4: exec: uvicorn: not found
...(繰り返し)
真の原因が判明: uvicorn コマンドが見つからず、コンテナが起動→クラッシュ→再起動を繰り返していました。Dev Container のエラーは、この不安定なコンテナに接続しようとして失敗したものでした。
Step 3: なぜ uvicorn が見つからないのか?
Dockerfile を確認すると、正しく依存関係をインストールしているように見えました:
# Development Stage
FROM base AS development
# 仮想環境をコピー
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
# 開発依存もインストール
RUN uv sync --no-install-project
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
しかし、docker-compose.yml を見ると問題がありました:
services:
app:
volumes:
- .:/app # <- ここが問題!
根本原因:
- Docker ビルド時に
/app/.venvに依存関係がインストールされる - コンテナ起動時に
volumes: - .:/appでホストディレクトリがマウントされる - ホストに
.venvが存在しないため、Docker イメージ内の.venvが「見えなくなる」 - 結果として
uvicornコマンドが PATH に存在しない
解決策
修正1: docker-compose.yml で .venv を保護
Anonymous volume を使用して、Docker イメージ内の .venv がホストのマウントで上書きされないようにします。
services:
app:
volumes:
- .:/app
# 仮想環境をホストのマウントから保護
- /app/.venv
この設定により、/app/.venv は Docker イメージ内のものが使用され、ホストのマウントの影響を受けません。
修正2: Dockerfile の --frozen オプション
uv.lock ファイルがない場合でもビルドできるよう、--frozen オプションを外しました:
# 修正前
RUN uv sync --frozen --no-dev --no-install-project
# 修正後
RUN uv sync --no-dev --no-install-project
修正3: 依存関係の追加(おまけ)
調査中に発見した別の問題として、pydantic[email] が必要でした:
# pyproject.toml
dependencies = [
"pydantic[email]>=2.9.0", # email-validator を含む
]
再構築手順
問題を解決した後、以下の手順でコンテナを再構築しました:
# 1. コンテナを停止・削除
docker compose down
# 2. キャッシュなしで再ビルド
docker compose build --no-cache
# 3. コンテナを起動
docker compose up -d
# 4. 状態を確認
docker ps
docker logs mvp-boost-app
教訓と予防策
1. エラーメッセージを鵜呑みにしない
Dev Container の「An error occurred setting up the container」は、様々な原因で発生する汎用的なエラーです。必ず以下を確認しましょう:
# コンテナの状態を確認
docker ps -a
# コンテナのログを確認
docker logs <container_name>
2. Volume マウントの落とし穴を理解する
Docker Compose で .:/app のようなバインドマウントを使用する場合、Docker イメージでインストールした依存関係がホストのディレクトリで上書きされる可能性があります。
解決パターン:
volumes:
- .:/app
- /app/.venv # Anonymous volume で保護
- /app/node_modules # Node.js の場合
3. Exit code の意味を知る
| Exit Code | 意味 |
|---|---|
| 0 | 正常終了 |
| 1 | 一般的なエラー |
| 127 | コマンドが見つからない |
| 128 | 無効な引数 |
| 137 | SIGKILL (メモリ不足等) |
| 139 | Segmentation fault |
4. デバッグ用のチェックリスト
Dev Container が起動しない場合のチェックリスト:
- Docker Desktop は起動しているか?
-
docker ps -aでコンテナの状態を確認 -
docker logs <container>でエラーログを確認 -
docker context showでコンテキストを確認 - Volume マウントで依存関係が上書きされていないか?
まとめ
今回の問題の流れを整理すると:
VS Code Dev Container エラー
↓
「An error occurred setting up the container」
↓
実は app コンテナが Restarting (127) 状態
↓
docker logs で「uvicorn: not found」を発見
↓
Volume マウントで .venv が上書きされていた
↓
docker-compose.yml に /app/.venv を追加して解決
Dev Container のエラーメッセージは原因を隠してしまうことがあります。docker ps と docker logs を活用して、本当の原因を突き止めましょう。
修正後の設定ファイル
docker-compose.yml(抜粋)
services:
app:
build:
context: .
dockerfile: Dockerfile
target: development
volumes:
- .:/app
# Named volumeで.venvを永続化(ホストには作成されない)
- venv_data:/app/.venv
ports:
- "4100:8000"
volumes:
venv_data: # Python仮想環境を永続化
ポイント: Anonymous volume (/app/.venv) ではなく Named volume (venv_data:/app/.venv) を使用することで:
- ホストに
.venvが作成されない -
docker compose downしても依存関係が保持される - コンテナ再作成時の
uv syncが高速化
Dockerfile(抜粋)
# Development Stage
FROM base AS development
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
COPY --from=builder /app/.venv /app/.venv
ENV PATH="/app/.venv/bin:$PATH"
COPY pyproject.toml uv.lock* ./
RUN uv sync --no-install-project
# Entrypoint スクリプト
COPY scripts/docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
COPY . .
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
scripts/docker-entrypoint.sh
#!/bin/sh
set -e
echo "Container started"
# Named volume が空の場合、依存関係をインストール
if [ ! -f /app/.venv/bin/uvicorn ]; then
echo "Installing dependencies..."
uv sync --no-install-project
fi
exec "$@"
ポイント: Named volume は初回起動時に空なので、entrypoint で依存関係の存在をチェックし、なければインストールします。