Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/CD.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: CD

on:
workflow_call:
workflow_dispatch:

jobs:
deploy:
runs-on: self-hosted
steps:
- name: SSH and Deploy
run: |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
- name: Add deploy host key
run: |
mkdir -p ~/.ssh
ssh-keyscan -H "${{ secrets.CONTAINER_IP }}" >> ~/.ssh/known_hosts

- name: SSH and Deploy
run: |
ssh deploy-user@${{ secrets.CONTAINER_IP }} << 'EOF'
set -e
cd /home/deploy-user/SeeFT
echo '${{ secrets.HARBOR_PASS }}' | docker login '${{ secrets.HARBOR_REG }}' -u '${{ secrets.HARBOR_USERNAME }}' --password-stdin
docker compose -f docker-compose.cd.yml pull
docker compose -f docker-compose.cd.yml up -d
Comment thread
FastDefence marked this conversation as resolved.
docker image prune -f
EOF
set -e
cd /home/deploy-user/SeeFT
git fetch origin main
git reset --hard origin/main
echo '${{ secrets.HARBOR_PASS }}' | docker login '${{ secrets.HARBOR_REG }}' -u '${{ secrets.HARBOR_USERNAME }}' --password-stdin
docker compose -f docker-compose.cd.yml pull
docker compose -f docker-compose.cd.yml up -d
docker image prune -f
EOF
84 changes: 84 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: CI

on:
push:
branches:
- main
workflow_call:
workflow_dispatch:

jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Check out the repo
uses: actions/checkout@v6
with:
submodules: recursive
token: ${{ secrets.GH_PAT || github.token }}

- name: Connect to Tailscale
uses: tailscale/github-action@v2
with:
oauth-client-id: ${{ secrets.TAILSCALE_OAUTH_CLIENT_ID }}
oauth-secret: ${{ secrets.TAILSCALE_OAUTH_CLIENT_SECRET }}
tags: tag:ci

- name: Configure Insecure Registry
run: |
sudo service docker stop
echo "{\"insecure-registries\": [\"${{ secrets.HARBOR_REG }}\"]}" | sudo tee /etc/docker/daemon.json
sudo service docker start

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver-opts: network=host
config-inline: |
[registry."${{ secrets.HARBOR_REG }}"]
http = true
insecure = true
Comment thread
FastDefence marked this conversation as resolved.
Outdated

- name: Log in to Harbor
uses: docker/login-action@v3
with:
registry: ${{ secrets.HARBOR_REG }}
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASS }}

- name: Create .env file
run: |
mkdir -p mobile/env
echo "${{ secrets.SEEFT_MOBILE_ENVS }}" > mobile/env/.env
Comment thread
FastDefence marked this conversation as resolved.
Outdated

- name: Build and Push API
uses: docker/build-push-action@v5
with:
context: ./api
file: ./api/prod.Dockerfile
push: true
tags: ${{ secrets.HARBOR_REG }}/seeft/api:latest
cache-from: type=gha

- name: Build and Push Admin
uses: docker/build-push-action@v5
with:
context: ./admin
file: ./admin/prod.Dockerfile
push: true
tags: ${{ secrets.HARBOR_REG }}/seeft/admin:latest
cache-from: type=gha

- name: Build and Push Mobile
uses: docker/build-push-action@v5
with:
context: ./mobile
file: ./mobile/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REG }}/seeft/mobile:latest
cache-from: type=gha

trigger-cd:
needs: build-and-push
uses: ./.github/workflows/CD.yml
secrets: inherit
44 changes: 44 additions & 0 deletions docker-compose.cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
version: "3"
services:
cloudflare:
image: "cloudflare/cloudflared:latest"
container_name: "nutfes-seeft-web"
volumes: ["./web/prod:/home/nonroot/.cloudflared"]
command: tunnel run

mobile:
image: ${HARBOR_REG}/seeft/mobile:latest
container_name: "nutfes-seeft-mobile"
command: "python3 ./python/server.py"
ports: ["45029:45029"]
environment:
NEXT_PUBLIC_APP_ENV: "production"
depends_on: ["api"]
restart: always

api:
image: ${HARBOR_REG}/seeft/api:latest
container_name: "nutfes-seeft-api"
volumes: ["./api:/env/app"]
command: sh -c "go build -o main main.go && ./main"
Comment on lines +22 to +23
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don’t compile Go at container startup in CD compose.

Lines 22-23 bind-mount source and run go build on startup, which breaks immutable-deploy assumptions and can fail if runtime image lacks toolchain.

Suggested direction
   api:
     image: ${HARBOR_REG}/seeft/api:latest
     container_name: "nutfes-seeft-api"
-    volumes: ["./api:/env/app"]
-    command: sh -c "go build -o main main.go && ./main"
+    # rely on the image artifact built in CI
+    # command should be provided by Dockerfile CMD/ENTRYPOINT
     env_file: ["./api/env/seeft.env"]
     ports: ["1234:1234"]
     restart: always
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose.cd.yml` around lines 22 - 23, The docker-compose.cd.yml
currently bind-mounts the source (volumes: ["./api:/env/app"]) and runs a build
at container start (command: sh -c "go build -o main main.go && ./main"), which
violates immutable deploys and requires the Go toolchain at runtime; remove the
bind-mount and replace the runtime command so the container runs the prebuilt
artifact produced by CI (e.g., drop volumes: ["./api:/env/app"] and change the
command to just run the compiled binary such as ./main or rely on the image's
CMD), and ensure the CI pipeline builds a multi-stage Docker image that contains
the compiled binary referenced by this compose file instead of compiling in the
container.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FastDefence はい、まさにその通りです!マルチステージビルドを使って prod.Dockerfile 内でコンパイルするのがベストプラクティスです。


なぜ Dockerfile 内でビルドすべきか

現状の問題 Dockerfile 内でビルドした場合
ランタイムイメージに Go ツールチェーンが必要 最終イメージに Go ツールチェーン不要(軽量化)
起動のたびにビルドが走り、起動が遅い CI でビルド済みのバイナリを実行するだけで高速
ソースコードをサーバにマウントする必要がある イメージが自己完結(immutable deploy)

api/prod.Dockerfile の修正例(マルチステージビルド)

# --- ビルドステージ ---
FROM golang:1.23-alpine AS builder
WORKDIR /app

COPY go.mod go.sum ./
RUN go mod download

COPY . .
RUN go build -o main main.go

# --- ランタイムステージ ---
FROM alpine:3.20
WORKDIR /app

COPY --from=builder /app/main .

EXPOSE 1234
CMD ["./main"]

docker-compose.cd.yml の修正例

  api:
    image: ${HARBOR_REG}/seeft/api:latest
    container_name: "nutfes-seeft-api"
    # volumes と command を削除 — Dockerfile の CMD に委ねる
    env_file: ["./api/env/seeft.env"]
    ports: ["1234:1234"]
    restart: always

volumes: ["./api:/env/app"]command: sh -c "go build ..." を削除することで、CI でビルドされたイメージをそのまま実行するだけになります。seeft.env は引き続きサーバ上のファイルから読み込まれる設計のままです(既存の学習内容と一致)。

(ノ´ヮ´)ノ*:・゚✧


🧠 Learnings used
Learnt from: FastDefence
Repo: NUTFes/SeeFT PR: 262
File: docker-compose.cd.yml:24-24
Timestamp: 2026-04-18T19:42:09.584Z
Learning: In the SeeFT repository, `api/env/seeft.env` is intentionally NOT tracked in git. It is a production secret environment file that is manually provisioned directly on the deployment server (`/home/deploy-user/SeeFT`). The `docker-compose.cd.yml` file references it via `env_file: ["./api/env/seeft.env"]` and this is by design — do not flag it as a missing or untracked file in future reviews.

env_file: ["./api/env/seeft.env"]
Comment thread
coderabbitai[bot] marked this conversation as resolved.
ports: ["1234:1234"]
restart: always

admin:
image: ${HARBOR_REG}/seeft/admin:latest
container_name: "nutfes-seeft-admin"
command: sh -c "npm install && npm run build && npm run start"
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Apr 18, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid runtime npm install/build in production container start command.

Line 31 makes startup dependent on live package install/build, increasing failure risk and startup time. Prefer running only the prebuilt app command from the image.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docker-compose.cd.yml` at line 31, The service command currently runs "sh -c
\"npm install && npm run build && npm run start\"" at container start; change it
to only run the prebuilt start command (e.g., "npm run start" or the production
node entrypoint) and ensure the image is built with dependencies and the
production build in the Dockerfile/CI pipeline instead of installing/building at
runtime; update the docker-compose service to remove "npm install" and "npm run
build" from the command and verify the Dockerfile produces the built app and
proper CMD/ENTRYPOINT so the compose file just invokes the runtime start
command.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find prod.Dockerfile for admin
fd -i "prod.Dockerfile" --exec echo {}
fd -i "Dockerfile" --exec echo {}

Length of output: 147


🏁 Script executed:

#!/bin/bash
cat ./admin/prod.Dockerfile
echo "---"
cat ./admin/Dockerfile

Length of output: 283


@FastDefence はい、Dockerfile内でビルドするのが正しいアプローチです。

現在の admin/prod.Dockerfile を確認すると、npm installnpm run build が実行されておらず、CMD/ENTRYPOINT も設定されていないため、docker-compose 側でそれらを補っている状態になっています。

以下のように prod.DockerfileRUNCMD を追加することを推奨します:

# admin/prod.Dockerfile
FROM node:16.13.0

WORKDIR /app/next-project/seeft-admin
COPY ./ /app

ENV NEXT_PUBLIC_APP_ENV production

# ← ここでビルドまで完結させる
RUN npm ci && npm run build

CMD ["npm", "run", "start"]

そして docker-compose.cd.ymladmin サービスから command を削除します:

admin:
  image: ${HARBOR_REG}/seeft/admin:latest
  container_name: "nutfes-seeft-admin"
  # command は不要(DockerfileのCMDが使われる)
  ports: ["5000:3000"]
  environment:
    NEXT_PUBLIC_APP_ENV: "production"
  stdin_open: true
  tty: true
  depends_on: ["api"]
  restart: always

この変更のメリット:

現在(runtime build) 改善後(image build)
起動時間 遅い(install+buildが毎回走る) 速い(起動のみ)
障害リスク npm registry障害で起動失敗の可能性 イメージ作成時に完結
再現性 コンテナ毎に差異が出うる CIでビルドしたものがそのまま動く
イメージサイズ ビルドキャッシュが残る multi-stage buildでさらに削減可能

なお、api サービスの command: sh -c "go build -o main main.go && ./main" も同様の問題があります。api/prod.Dockerfile にも RUN go build -o main main.goCMD ["./main"] を追加することをお勧めします。


🧠 Learnings used
Learnt from: FastDefence
Repo: NUTFes/SeeFT PR: 262
File: docker-compose.cd.yml:24-24
Timestamp: 2026-04-18T19:42:09.584Z
Learning: In the SeeFT repository, `api/env/seeft.env` is intentionally NOT tracked in git. It is a production secret environment file that is manually provisioned directly on the deployment server (`/home/deploy-user/SeeFT`). The `docker-compose.cd.yml` file references it via `env_file: ["./api/env/seeft.env"]` and this is by design — do not flag it as a missing or untracked file in future reviews.

ports:
- "5000:3000"
environment:
NEXT_PUBLIC_APP_ENV: "production"
stdin_open: true
tty: true
depends_on: [api]
restart: always

networks:
default:
name: seeft-default
external: true
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated