ตัวอย่าง Dockerfile + docker-compose.yml Local Typhoon OCR n8n docker

Dockerfile

FROM n8nio/n8n:latest

USER root

# 0) Restore apk into the image (n8n image is Alpine but apk may be removed)
RUN set -eux; \
  ARCH="$(uname -m)"; \
  case "$ARCH" in \
    x86_64) ALP_ARCH="x86_64" ;; \
    aarch64) ALP_ARCH="aarch64" ;; \
    armv7l) ALP_ARCH="armv7" ;; \
    *) echo "Unsupported arch: $ARCH"; exit 1 ;; \
  esac; \
  apk_pkg="$(wget -qO- "https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/${ALP_ARCH}/" \
    | grep -o 'apk-tools-static-[0-9][^"]*\.apk' \
    | head -n 1)"; \
  wget -q "https://dl-cdn.alpinelinux.org/alpine/latest-stable/main/${ALP_ARCH}/${apk_pkg}"; \
  tar -xzf "${apk_pkg}" -C /; \
  ln -sf /sbin/apk.static /sbin/apk; \
  rm -f "${apk_pkg}"; \
  /sbin/apk --version

# 1) Install required packages (Alpine)
RUN apk update && apk add --no-cache \
    python3 \
    py3-pip \
    py3-virtualenv \
    poppler-utils \
    ffmpeg \
    build-base \
    ca-certificates \
    && update-ca-certificates

# 2) Create virtual env + install typhoon-ocr
RUN python3 -m venv /opt/venv && \
    /opt/venv/bin/pip install --no-cache-dir --upgrade pip setuptools wheel && \
    /opt/venv/bin/pip install --no-cache-dir typhoon-ocr

# 3) Use venv by default
ENV PATH="/opt/venv/bin:$PATH"

USER node

docker-compose.yml

services:
  # --- Traefik (Reverse Proxy & SSL) ---
  traefik:
    image: "traefik"
    restart: always
    command:
      - "--api=true"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.web.http.redirections.entryPoint.to=websecure"
      - "--entrypoints.web.http.redirections.entryPoint.scheme=https"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.mytlschallenge.acme.tlschallenge=true"
      - "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
      - "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - traefik_data:/letsencrypt
      - /var/run/docker.sock:/var/run/docker.sock:ro

  # --- n8n (Workflow Automation) ---
  n8n:
    build:
      context: .
      dockerfile: Dockerfile
    restart: always
    ports:
      - "192.168.31.219:5678:5678"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)"
      - "traefik.http.routers.n8n.entrypoints=websecure"
      - "traefik.http.routers.n8n.tls=true"
      - "traefik.http.routers.n8n.tls.certresolver=mytlschallenge"
      - "traefik.http.middlewares.n8n.headers.SSLRedirect=true"
      - "traefik.http.middlewares.n8n.headers.STSSeconds=315360000"
      - "traefik.http.middlewares.n8n.headers.browserXSSFilter=true"
      - "traefik.http.middlewares.n8n.headers.contentTypeNosniff=true"
      - "traefik.http.middlewares.n8n.headers.forceSTSHeader=true"
      - "traefik.http.middlewares.n8n.headers.SSLHost=${DOMAIN_NAME}"
      - "traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true"
      - "traefik.http.middlewares.n8n.headers.STSPreload=true"
      - "traefik.http.routers.n8n.middlewares=n8n@docker"
    environment:
      - N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
      - GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
      - N8N_PROXY_HOPS=1
      - TYPHOON_OCR_API_KEY=${TYPHOON_OCR_API_KEY}
      - N8N_N8N_FILESYSTEM_ROOT=/doc
      - NODES_EXCLUDE=[]
      - N8N_RESTRICT_FILE_ACCESS_TO=/doc
      - N8N_SECURE_COOKIE=false
      - TYPHOON_OCR_API_KEY=sk-DyyHJmF46DuqDPYhL0d1xX6HuadBLt6iTktkajyA0rQYa8M
    volumes:
      - n8n_data:/home/node/.n8n
      - ./doc:/doc

  # --- Ollama (Local AI Model) ---
  #ollama:
  #  image: ollama/ollama:latest
  #  container_name: ollama
  #  restart: always
  #  volumes:
  #    - ollama_data:/root/.ollama

volumes:
  traefik_data:
  n8n_data:
  ollama_data: