Skip to content

Docker 설정

Docker 내에서 Artisan을 실행하려면 컨테이너에 Chrome 또는 Chromium 바이너리가 필요합니다. 이 가이드에서는 프로덕션 준비가 된 Dockerfile 패턴, Compose 구성, 보안 고려 사항 및 글꼴 지원을 다룹니다.

Dockerfile

최소 구성 (Debian 기반)

dockerfile
FROM php:8.3-cli

# Chromium 및 필수 라이브러리 설치
RUN apt-get update && apt-get install -y --no-install-recommends \
    chromium \
    fonts-liberation \
    libappindicator3-1 \
    libasound2 \
    libatk-bridge2.0-0 \
    libatk1.0-0 \
    libcups2 \
    libdbus-1-3 \
    libdrm2 \
    libgbm1 \
    libnspr4 \
    libnss3 \
    libx11-xcb1 \
    libxcomposite1 \
    libxdamage1 \
    libxrandr2 \
    xdg-utils \
    && rm -rf /var/lib/apt/lists/*

# Artisan 자동 감지를 위한 Chrome 경로 설정
ENV CHROME_PATH=/usr/bin/chromium

# Composer 종속성 설치
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

Alpine 기반 (더 작은 이미지)

dockerfile
FROM php:8.3-cli-alpine

RUN apk add --no-cache \
    chromium \
    nss \
    freetype \
    harfbuzz \
    ca-certificates \
    ttf-freefont \
    font-noto-cjk

ENV CHROME_PATH=/usr/bin/chromium-browser

COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY . .

Docker Compose

yaml
services:
  app:
    build: .
    volumes:
      - ./output:/app/output
    environment:
      CHROME_PATH: /usr/bin/chromium
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M
    # Docker에서 Chrome 샌드박싱에 필요
    security_opt:
      - seccomp=unconfined
    cap_add:
      - SYS_ADMIN

Docker용 Chrome 플래그

컨테이너의 Chrome은 안정적으로 실행하기 위해 특정 플래그가 필요합니다. 렌더러 생성 시 전달합니다.

php
use Yeeefang\TcpdfNext\Artisan\HtmlRenderer;

$renderer = HtmlRenderer::create(
    chromeFlags: [
        '--no-sandbox',              // seccomp 구성하지 않는 한 필수
        '--disable-setuid-sandbox',  // 보조 샌드박스 우회
        '--disable-gpu',             // 컨테이너에 GPU 없음
        '--disable-dev-shm-usage',   // /dev/shm 대신 /tmp에 쓰기
        '--disable-software-rasterizer',
        '--single-process',          // 간단한 렌더링에 메모리 절약
    ],
);

WARNING

--no-sandbox 플래그는 Chrome의 프로세스 샌드박스를 비활성화합니다. 프로덕션에서는 샌드박스를 활성화한 상태로 유지하고 컨테이너에 SYS_ADMIN 권한을 부여하거나 사용자 정의 seccomp 프로필을 사용하는 것이 좋습니다.

보안 고려 사항

옵션 A: 샌드박스 유지 (권장)

컨테이너에 SYS_ADMIN을 추가하고 --no-sandbox를 생략합니다.

yaml
services:
  app:
    cap_add:
      - SYS_ADMIN
    security_opt:
      - seccomp=chrome-seccomp.json

Chrome의 최소 seccomp 프로필은 Chromium 프로젝트 문서에서 찾을 수 있습니다.

옵션 B: 비루트 사용자

컨테이너 내에서 전용 비권한 사용자로 Chrome을 실행합니다.

dockerfile
RUN groupadd -r artisan && useradd -r -g artisan -G audio,video artisan \
    && mkdir -p /home/artisan/Downloads \
    && chown -R artisan:artisan /home/artisan

USER artisan

옵션 C: 읽기 전용 파일 시스템

루트 파일 시스템을 읽기 전용으로 마운트하고 Chrome을 위한 쓰기 가능한 tmpfs를 제공합니다.

yaml
services:
  app:
    read_only: true
    tmpfs:
      - /tmp
      - /home/artisan/.config

메모리 제한

Chrome은 특히 복잡한 페이지를 렌더링할 때 상당한 메모리를 소비할 수 있습니다. 컨테이너 제한을 설정하고 사용량을 모니터링하십시오.

페이지 복잡도권장 메모리
간단한 텍스트 (1--5 페이지)256 MB
테이블 및 이미지 (5--20 페이지)512 MB
복잡한 레이아웃, 차트, JS (20+ 페이지)1 GB+

Chrome이 메모리 부족 상태가 되면 코드 137(OOM killed)로 종료됩니다. Artisan의 RenderException은 이를 설명적 메시지로 래핑합니다.

php
// 메모리 폭주를 방지하기 위해 짧은 타임아웃으로 빠르게 실패
$options = RenderOptions::create()->setTimeout(15000);

글꼴 설치

Docker 이미지는 최소한의 글꼴과 함께 제공됩니다. 비라틴 스크립트와 브랜드 타이포그래피의 올바른 렌더링을 위해 추가 글꼴을 설치하십시오.

시스템 글꼴

dockerfile
# CJK 글꼴 (중국어, 일본어, 한국어)
RUN apt-get update && apt-get install -y \
    fonts-noto-cjk \
    fonts-noto-cjk-extra

# 아랍어, 히브리어, 데바나가리
RUN apt-get install -y \
    fonts-noto-core \
    fonts-noto-extra

# Google Fonts (예: Inter, Roboto)
RUN apt-get install -y fonts-inter

사용자 정의 글꼴

글꼴 파일을 컨테이너에 복사하고 fontconfig에 등록합니다.

dockerfile
COPY ./fonts/*.ttf /usr/share/fonts/custom/
RUN fc-cache -fv

웹 폰트

Artisan의 Chrome은 일반 브라우저처럼 렌더링 시 @font-face 웹 폰트를 가져올 수 있습니다. 추가 구성이 필요하지 않지만, 컨테이너가 폰트 CDN에 네트워크 접근이 가능한지 확인하십시오.

css
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');

body {
    font-family: 'Inter', sans-serif;
}

헬스 체크

Chrome이 작동하는지 확인하는 헬스 체크를 추가합니다.

dockerfile
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD chromium --headless=new --disable-gpu --no-sandbox \
        --dump-dom about:blank > /dev/null 2>&1 || exit 1

전체 프로덕션 예제

dockerfile
FROM php:8.3-cli-bookworm AS base

# 시스템 종속성 + Chromium
RUN apt-get update && apt-get install -y --no-install-recommends \
    chromium \
    fonts-liberation \
    fonts-noto-cjk \
    libnss3 libgbm1 libatk-bridge2.0-0 \
    && rm -rf /var/lib/apt/lists/*

ENV CHROME_PATH=/usr/bin/chromium

# 비루트 사용자
RUN groupadd -r artisan && useradd -r -g artisan artisan \
    && mkdir -p /home/artisan && chown artisan:artisan /home/artisan

WORKDIR /app

COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader

COPY --chown=artisan:artisan . .

USER artisan

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD chromium --headless=new --no-sandbox --dump-dom about:blank > /dev/null 2>&1

CMD ["php", "artisan", "render:process"]

다음 단계

  • 고급 기능 -- Chrome 구성, 연결 풀링, 오류 처리.
  • 개요 -- 패키지 요약 및 설치.

LGPL-3.0-or-later 라이선스로 배포됩니다.