Skip to content

Docker compose restart policy

Restart policy

ใน docker compose services หาก service ตายไป เราสามารถให้ docker restart ตัวเองกลับมาได้ด้วย

yaml
networks:
  my_bridge2:
    external: true
    name: my_bridge1

services:
  next:
    build:
      context: .
    environment:
      NODE_ENV: production
    ports:
      - 3001:3000
    restart: unless-stopped
    networks:
      - my_bridge2
  backend:
    container_name: hono
    image: hono
    environment:
      NODE_ENV: production
    ports:
      - 3333:3333
    volumes:
      - ./uploads:/app/uploads
    restart: unless-stopped
    networks:
      - my_bridge2

โดย option ที่ใส่ได้ก็จะมี

  • no คือไม่ต้อง restart
  • always จะ restart เสมอ จนกว่ามันจะถูกลบออกไป
  • on-failure[:max number of retries] จะ restart เมื่อ container ตาย ระบุจำนวนการ restart ได้ด้วย
  • unless-stopped จะ restart เมื่อ container ตาย แต่ถ้าเรา stop ไว้ มันจะไม่ restart กลับมาเองนะ

Health check

จากการที่เราใส่ restart policy เข้าไปนั้น มันจะ restart ก็ต่อเมื่อ container มันตายไป หรือได้ exit code มา

การใส่ Health check คือการที่เราบอก docker ถึงวิธีการที่จะทำให้ docker รู้ว่า container เรายังทำงานอยู่ดีไหม เมื่อ health check failed ก็จะไป restart container ไปตาม restart policy ที่ตั้งไว้

เราสามารถใส่ Health check แบบนี้

yaml
networks:
  my_bridge2:
    external: true
    name: my_bridge1

services:
  next:
    build:
      context: .
    environment:
      NODE_ENV: production
    ports:
      - 3001:3000
    restart: unless-stopped
    healthcheck: 
      test: ["CMD-SHELL", "curl -f http://localhost:3000 || exit 1"] 
      interval: 1m
      timeout: 10s
      retries: 3
      start_period: 0s
    networks:
      - my_bridge2
  backend:
    container_name: hono
    image: hono
    environment:
      NODE_ENV: production
    ports:
      - 3333:3333
    volumes:
      - ./uploads:/app/uploads
    restart: unless-stopped
    healthcheck: 
      test: ["CMD-SHELL", "curl -f http://localhost:3333/healthz || exit 1"] 
      interval: 1m
      timeout: 10s
      retries: 3
      start_period: 20s
    networks:
      - my_bridge2

จะเห็นว่าเราใช้ curl ในการ check container health

ฉนั้นเราต้องใส่ curl package ลงไปใน container ด้วย

ยกตัวอย่างส่วนของ backend ละกัน

# Dockerfile
# syntax=docker/dockerfile:1
ARG NODE_VERSION=22.2.0
ARG PNPM_VERSION=8.15.5

# Build
FROM node:${NODE_VERSION}-alpine AS build

# Install pnpm.
RUN --mount=type=cache,target=/root/.npm \
  npm install -g pnpm@${PNPM_VERSION}


WORKDIR /app

RUN --mount=type=bind,source=package.json,target=package.json \
  --mount=type=bind,source=pnpm-lock.yaml,target=pnpm-lock.yaml \
  --mount=type=cache,target=/root/.local/share/pnpm/store \
  pnpm install --frozen-lockfile

COPY . .

RUN pnpm run build && pnpm prune --prod

# Final
FROM node:${NODE_VERSION}-alpine AS runner

ENV NODE_ENV=production
WORKDIR /app

RUN apk --no-cache add curl

# add nonroot user and group
RUN addgroup --system --gid 1001 nodejs && adduser --system --uid 1001 nonroot

# make uploads folder 
RUN mkdir -p ./uploads && chmod 700 ./uploads && chown -R nonroot:nodejs ./uploads

# when copy use flag --chown=<user>:<group>
COPY --from=build --chown=nonroot:nodejs /app/dist ./dist
COPY --from=build --chown=nonroot:nodejs /app/node_modules ./node_modules
COPY --from=build --chown=nonroot:nodejs /app/package.json ./package.json

# finally use nonroot user
USER nonroot

EXPOSE 3333

CMD ["node", "dist/index.js"]