astro-docker

Astro Docker

Astroプロジェクトをコンテナ化するためのDocker設定について説明します。

静的サイトのDocker化

静的ビルド(output: 'static')の場合、ビルド結果を軽量なWebサーバーで配信します。

Nginxを使用

# Dockerfile
FROM node:20-alpine AS build
WORKDIR /app

# 依存関係のインストール
COPY package*.json ./
RUN npm ci

# ビルド
COPY . .
RUN npm run build

# 本番環境
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

nginx.conf:

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    # SPA用のフォールバック(必要に応じて)
    location / {
        try_files $uri $uri/ /index.html;
    }

    # キャッシュ設定
    location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # gzip圧縮
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;
}

Serveを使用(軽量)

# Dockerfile
FROM node:20-alpine AS build
WORKDIR /app

COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
RUN npm install -g serve
COPY --from=build /app/dist ./dist
EXPOSE 3000
CMD ["serve", "-s", "dist", "-l", "3000"]

SSRサイトのDocker化

SSR(output: 'server')の場合、Node.jsランタイムが必要です。

Node.jsアダプター使用

# Dockerfile
FROM node:20-alpine AS build
WORKDIR /app

COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app

# 本番用依存関係のみ
COPY package*.json ./
RUN npm ci --omit=dev

# ビルド成果物をコピー
COPY --from=build /app/dist ./dist

ENV HOST=0.0.0.0
ENV PORT=4321

EXPOSE 4321
CMD ["node", "./dist/server/entry.mjs"]

astro.config.mjsの設定

// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';

export default defineConfig({
  output: 'server',
  adapter: node({
    mode: 'standalone',
  }),
});

Docker Compose

静的サイト

# compose.yaml
services:
  web:
    build: .
    ports:
      - "8080:80"
    restart: unless-stopped

SSRサイト

# compose.yaml
services:
  web:
    build: .
    ports:
      - "4321:4321"
    environment:
      - NODE_ENV=production
      - HOST=0.0.0.0
      - PORT=4321
    restart: unless-stopped

開発環境

# compose.override.yaml
services:
  web:
    build:
      context: .
      target: build  # ビルドステージで止める
    volumes:
      - .:/app
      - /app/node_modules  # node_modulesは除外
    ports:
      - "4321:4321"
    command: npm run dev -- --host 0.0.0.0

.dockerignore

node_modules
dist
.git
.gitignore
.env
.env.*
*.md
.vscode
.idea

マルチステージビルドの利点

上記のDockerfileはマルチステージビルドを使用しています:

  1. ビルドステージbuild): 依存関係インストール・ビルド
  2. 本番ステージ: 最小限のランタイムのみ

メリット:

  • イメージサイズの削減
  • 開発用ツールが本番イメージに含まれない
  • セキュリティの向上

環境変数

ビルド時の環境変数

ARG PUBLIC_API_URL
ENV PUBLIC_API_URL=$PUBLIC_API_URL
RUN npm run build
docker build --build-arg PUBLIC_API_URL=https://api.example.com -t myapp .

実行時の環境変数

# compose.yaml
services:
  web:
    environment:
      - SECRET_API_KEY=${SECRET_API_KEY}

ヘルスチェック

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:4321/ || exit 1

Traefik連携

リバースプロキシとしてTraefikを使用する場合:

# compose.yaml
services:
  web:
    build: .
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.astro.rule=Host(`example.com`)"
      - "traefik.http.services.astro.loadbalancer.server.port=4321"
    networks:
      - traefik

networks:
  traefik:
    external: true

詳細はTraefikを参照してください。

パフォーマンス最適化

レイヤーキャッシュの活用

# 依存関係を先にコピー(変更が少ない)
COPY package*.json ./
RUN npm ci

# ソースコードを後でコピー(変更が多い)
COPY . .
RUN npm run build

Alpineベースイメージ

Node.jsのAlpineイメージを使用してイメージサイズを削減:

FROM node:20-alpine

参考