PHP 애플리케이션 컨테이너화
운영 환경에 바로 사용할 수 있는 PHP Dockerfile을 작성합니다.
PHP 애플리케이션 컨테이너화은(는) CoddyKit의 무료 PHP Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 PHP Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
PHP를 컨테이너화하는 이유
PHP를 재현 가능하게 배포한다는 것은 정확한 인터프리터 버전, 확장 기능 및 OS 라이브러리를 코드와 함께 고정하는 것입니다. Docker 이미지를 사용하면 노트북, CI, 운영 환경 등 모든 환경에서 동일한 php -v와 동일한 ext-* 집합을 사용하게 됩니다.
이 레슨에서는 운영 환경에 바로 사용할 수 있는 이미지를 만듭니다. PHP-FPM, 필요한 확장 기능만 포함하고, 설정을 조정하며, 루트가 아닌 사용자와 상태 확인을 사용합니다.
FPM과 아파치 기반 이미지 비교
공식 PHP 이미지는 여러 변형으로 제공됩니다. nginx/Traefik 뒤에서 실행하는 운영용 웹 애플리케이션에는 php:8.3-fpm-alpine(작은 이미지) 또는 php:8.3-fpm(Debian 기반, glibc 사용으로 네이티브 라이브러리 관련 문제가 적음)을 선호하십시오.
cli— 작업 프로세스, 대기열, 예약 작업fpm— FastCGI 프로세스 관리자, nginx와 함께 사용apache— 아파치가 포함된 구성으로 편리하지만 더 무거움
마이너 버전을 고정하십시오. 운영 환경에서는 :latest를 절대 사용하지 마십시오.
# Base image choice in your Dockerfile
FROM php:8.3-fpm-alpine AS base
# Why alpine? ~30MB base vs ~140MB Debian.
# Tradeoff: musl libc, occasional native-extension friction.확장 기능 설치하기
이 이미지 안에서 apt install php-xxx를 절대 실행하지 마십시오. 이미지에 포함된 도우미인 docker-php-ext-install, docker-php-ext-configure, pecl을 사용하십시오. install-php-extensions 스크립트(mlocati)는 필요한 개발 헤더를 대신 가져오는 사실상의 지름길입니다.
FROM php:8.3-fpm-alpine
# Grab the helper that resolves build deps automatically
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions \
pdo_mysql \
opcache \
intl \
zip \
redis \
bcmath이미지에 Composer 포함하기
설치 프로그램을 내려받는 대신 공식 이미지에서 Composer 바이너리를 복사하십시오. 운영 환경에서는 --no-dev 및 --optimize-autoloader와 함께 composer install을 실행하고, 먼저 오직 composer.json/composer.lock만 복사하십시오. 그러면 소스 변경과 무관하게 의존성 계층을 캐시할 수 있습니다.
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
# Cache-friendly: deps layer invalidates only when lock changes
COPY composer.json composer.lock ./
RUN composer install \
--no-dev \
--no-scripts \
--no-autoloader \
--prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritativephp.ini 조정하기
기본 이미지에는 php.ini-production 및 php.ini-development 템플릿이 포함되어 있습니다. 운영용 템플릿을 활성화한 다음 자체 재정의 설정을 conf.d에 추가하십시오. 이 디렉터리는 마지막에 병합되므로 자체 설정이 우선 적용됩니다.
운영 환경의 주요 값은 opcache.enable=1, opcache.validate_timestamps=0(이미지 안의 불변 코드에 적합), 합리적인 memory_limit입니다.
# Activate production ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Custom overrides win because conf.d loads last
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.iniOPcache 재정의 파일
이 설정은 운영 환경에서 가장 큰 개선 효과를 냅니다. validate_timestamps=0이면 PHP가 각 요청마다 파일 상태를 확인하지 않습니다. 하지만 그만큼 변경 사항을 배포하려면 이미지를 다시 빌드해야 합니다. 불변 컨테이너에는 이것이 정확히 우리가 원하는 방식입니다.
; docker/php/zz-app.ini
memory_limit = 256M
expose_php = Off
opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.preload = /app/preload.php
opcache.preload_user = www-data루트가 아닌 사용자로 실행하기
이미지에는 이미 www-data가 정의되어 있습니다. FPM을 루트로 실행하는 것은 공격 표면을 불필요하게 넓히는 일입니다. 쓰기 가능한 경로(캐시, 로그)의 소유권을 설정하고 CMD 전에 USER로 사용자를 전환하십시오.
FPM의 마스터 프로세스가 권한이 필요한 포트에 바인딩해야 하나요? 아닙니다. FPM은 9000번 포트에서 수신하므로 루트가 아닌 사용자로 쉽게 실행할 수 있습니다.
# Make runtime-writable dirs owned by the runtime user
RUN chown -R www-data:www-data /app/var /app/storage 2>/dev/null || true
USER www-data
EXPOSE 9000
CMD ["php-fpm"]상태 확인
오케스트레이터는 프로세스가 존재한다는 사실만이 아니라 FPM이 실제로 작동 중이라는 신호를 필요로 합니다. cgi-fcgi는 FPM의 /status 또는 /ping 엔드포인트를 ping할 수 있습니다. 먼저 FPM 풀에서 pm.status_path와 ping.path를 활성화하십시오.
# In www.conf pool config:
; ping.path = /ping
; ping.response = pong
# Dockerfile HEALTHCHECK using cgi-fcgi
RUN install-php-extensions @composer >/dev/null 2>&1 || true
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
CMD SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1Dockerfile 구성하기
다음은 일관된 단일 스테이지 운영용 Dockerfile입니다. 다음 레슨에서는 빌드 도구를 제거하기 위해 이를 멀티 스테이지로 나눕니다. 순서는 의존성 → 설정 → 소스 코드 → 자동 로드 → 사용자 전환입니다.
FROM php:8.3-fpm-alpine
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
install-php-extensions pdo_mysql opcache intl zip redis
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative && \
chown -R www-data:www-data /app/var
USER www-data
EXPOSE 9000
CMD ["php-fpm"]빌드 확인
빌드한 후 실제로 이미지에 포함된 내용을 간단히 점검하십시오. PHP 버전, 로드된 확장 기능, 그리고 OPcache 검증이 꺼져 있는지 확인합니다. 간단한 CLI 스크립트로 앱이 의존하는 실행 환경 계약을 확인할 수 있습니다.
<?php
// Run inside the container: php verify.php
echo 'PHP ' . PHP_VERSION . PHP_EOL;
$required = ['pdo_mysql', 'opcache', 'intl', 'zip'];
foreach ($required as $ext) {
printf("%-12s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'MISSING');
}
var_dump((bool) ini_get('opcache.enable'));
?>빌드 컨텍스트 정리
.dockerignore는 빌드 컨텍스트를 작게 유지하고 비밀 정보와 vendor의 불필요한 내용이 이미지에 유입되거나 캐시를 무효화하지 않도록 합니다. vendor, VCS, env 파일, 로컬 도구를 제외하십시오.
# .dockerignore
.git
.gitignore
vendor/
node_modules/
.env
.env.*
tests/
*.md
docker-compose*.yml
storage/logs/*
var/cache/*빠른 확인
운영용 이미지에서 opcache.validate_timestamps=0으로 설정하는 이유는 무엇입니까?
요약
운영용 PHP-FPM 이미지를 구성했습니다. 8.3-fpm-alpine 기반 이미지를 고정하고, 설치 스크립트를 통해 필요한 확장 기능만 설치했으며, Composer와 캐시된 의존성을 별도 레이어에 복사했습니다. 또한 OPcache 재정의가 적용된 운영용 php.ini을 활성화하고, www-data로 사용자를 전환했으며, FPM 상태 확인을 추가했습니다.
핵심 습관: 버전을 고정하고, 의존성 레이어를 캐시하며, 루트가 아닌 사용자로 실행하고, 타임스탬프 검증을 비활성화하며, .dockerignore로 빌드 컨텍스트를 작게 유지하십시오.
자주 묻는 질문
“PHP 애플리케이션 컨테이너화” 강의는 무료인가요?
네 — “PHP 애플리케이션 컨테이너화” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 PHP Academy 강의 전체를 잠금 해제할 수 있습니다. PHP Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“PHP 애플리케이션 컨테이너화”에서 뭘 배우나요?
운영 환경에 바로 사용할 수 있는 PHP Dockerfile을 작성합니다. 브라우저에서 직접 실행하는 실습 코드로 PHP Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
PHP Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 PHP Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.
“PHP 애플리케이션 컨테이너화” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 PHP Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 PHP Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- PHP 애플리케이션 컨테이너화
- 다단계 빌드와 최적화
- 로컬 스택을 위한 Docker Compose
- GitHub Actions로 CI/CD 구축