記事投稿日: 2026年2月1日(日)
最終更新日: 2026年2月1日(日)
シェル芸オンラインジャッジというウェブサイトを開発しています。 今回はフロントエンドとバックエンドをDockerコンテナ内で動かすように変更しました。 nginxもコンテナ内で動かしています。
シェル芸オンラインジャッジシェル芸オンラインジャッジのソースコードを丸ごとGeminiに渡して、 具体的に修正方法を聞いて修正しました。 今回はDockerfileやdocker-compose.yml、nginxのconfファイルなどについて教えてもらいました。
Nano Banana Proに生成してもらった現状のシステム構成図です。
下記がフロントエンドのDockerfileです。 主にフロントエンド側のビルドとnginxの設定・起動を行っています。 問題データのファイルもコンテナ内にコピーしています。
# --- Build Stage ---
FROM node:22 AS builder
WORKDIR /app
COPY frontend/package.json frontend/yarn.lock* ./
RUN yarn install --frozen-lockfile
COPY frontend/ ./
RUN yarn build
# --- Serve Stage ---
FROM nginx:alpine
# ビルド成果物をNginxの公開ディレクトリにコピー
COPY --from=builder /app/build /usr/share/nginx/html
# 問題データを公開ディレクトリにコピー
COPY problems/ /usr/share/nginx/html/
# Nginx設定ファイルをコピー
COPY frontend/nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
nginxの設定ファイルはあらかじめ用意しておいてコンテナ内へコピーします。 一応80番ポートの設定を書いていますが、実際は443ポートだけ受け付けます。
server {
listen 80;
server_name shellgei-online-judge.com localhost;
# HTTP -> HTTPS リダイレクト
# location / {
# return 301 https://$host$request_uri;
# }
}
server {
listen 443 ssl;
server_name shellgei-online-judge.com localhost;
# SSL証明書の設定
ssl_certificate /etc/letsencrypt/live/shellgei-online-judge.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/shellgei-online-judge.com/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
root /usr/share/nginx/html;
index index.html;
# Docker内部のDNSサーバーを指定
resolver 127.0.0.11 valid=30s;
# フロントエンド (React)
location / {
try_files $uri $uri/ /index.html;
}
# バックエンド (FastAPI) へのプロキシ
location /api {
proxy_pass http://backend:8000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
下記がバックエンドのDockerfileです。 主にFastAPIの環境の作成を行っています。 こちらでも問題データのファイルをコンテナ内にコピーしています。
unixtime.txtやshellgei_id.txtというサーバ側のデータ管理用ファイルも作成しています(ここで作成していますが最終的にはdocker-compose.ymlのほうでホストからマウントしています)。 データ管理に関してはいずれデータベースをコンテナ内で動かす方針に移行したいです。
FROM python:3.12-slim
WORKDIR /app
# Poetryのインストール
RUN pip install poetry
# 依存関係ファイルのコピー (キャッシュ効率化のため先にコピー)
COPY pyproject.toml poetry.lock* ./
# 仮想環境を作成せずにシステムにインストール
RUN poetry config virtualenvs.create false \
&& poetry install --no-interaction --no-ansi --no-root
# ソースコードのコピー
COPY backend/ ./backend/
# 問題データのコピー
COPY problems/ ./backend/public/
# 作業ディレクトリをbackendに変更
WORKDIR /app/backend
RUN echo "0.0" > unixtime.txt && chmod 666 unixtime.txt \
&& echo "0" > shellgei_id.txt && chmod 666 shellgei_id.txt
# uvicornサーバーの起動
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
下記がシステム全体を起動するdocker-compose.ymlです。 バックエンドとフロントエンドのコンテナをそれぞれ起動しています。 バックエンド側ではコンテナ内からコンテナを操作するためにホスト側のDockerソケットをマウントしています。
フロントエンド側ではnginxの設定ファイルをマウントして使用しています。 また、ホスト側で用意したSSL証明書をマウントしています。
version: '3.8'
services:
backend:
build:
context: .
dockerfile: backend/Dockerfile
container_name: soj-backend
restart: always
volumes:
# ホストのDockerソケットをマウント (DooD)
- /var/run/docker.sock:/var/run/docker.sock
# データファイル
- ./backend_data/shellgei_id.txt:/app/backend/shellgei_id.txt
- ./backend_data/unixtime.txt:/app/backend/unixtime.txt
environment:
- TZ=Asia/Tokyo
frontend:
build:
context: .
dockerfile: frontend/Dockerfile
container_name: soj-frontend
restart: always
ports:
- "80:80" # HTTP
- "443:443" # HTTPS
volumes:
- ./frontend/nginx/default.conf:/etc/nginx/conf.d/default.conf
# ホスト側のSSL証明書のマウント
- /etc/letsencrypt:/etc/letsencrypt:ro
depends_on:
- backend
実行するシェル芸の時刻管理やID付けのために使用するデータファイルを作成するbashファイルを用意しました。 運用としてスマートではないので、今後データベースを使用するなどで対応したいです。
mkdir -p backend_data
echo "0.0" > backend_data/unixtime.txt
echo "0" > backend_data/shellgei_id.txt
chmod 666 backend_data/unixtime.txt
chmod 666 backend_data/shellgei_id.txt
シェル芸オンラインジャッジのリポジトリをダウンロードしてから下記コマンドを実行することで起動できます。 -dオプションを付けてバックグランドで実行しています。
cd /path/to/ShellgeiOnlineJudge/
bash create_backend_data.bash
docker compose up -d --build
以前より簡単に起動できるようになりました。 また、nginxの設定をしなくてよくなったことなど、ホスト側での準備が少なく済むようになって良かったです。
今回はシェル芸オンラインジャッジのシステムをDockerコンテナ内で動かせるように変更を加えました。 Geminiに聞いたら何でも教えてくれるのでとても助かります(たまに解決できないこともありましたが仕方なしです)。 運用が少し楽になって良かったです。 この調子でどんどん改善できたらと思います。 それでは、また。
各シリーズの記事を下記にまとめてあります。