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
คือไม่ต้อง restartalways
จะ 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"]