Docker

동봉된 Dockerfile과 compose.yaml은 컨테이너 하나가 사이트 하나를 서빙하는 구조입니다. 컨테이너는 Host와 관계없이 모든 요청을 FLEXAGON_PUBLIC 디렉터리(기본 public)로 보냅니다. 어떤 도메인을 어느 컨테이너에 연결할지는 로드밸런서·Ingress·Cloud Run 도메인 매핑이 정합니다.

타깃 용도 내용
dev 로컬 개발 (compose.yaml) 프로젝트를 /app에 마운트, php.ini-development, composer, Xdebug(설치만, 로드 안 함)
alpha·beta·production 스테이지별 배포 이미지 프로젝트를 복사하고 application/_Config/<스테이지>/의 파일로 application/을 덮어씀, composer install --no-dev, php.ini-production, opcache 타임스탬프 검사 끔, www-data로 실행, 빌드 중 flexagon check

PHP 8.3 + Apache 이미지이며, 컨테이너는 PORT(기본 8080)에서 듣습니다. 설치할 확장은 Dockerfile 맨 위의 PHP_EXTENSIONS에서 정하며, 쓰지 않는 것은 지우고 없는 것은 더합니다(DEPLOY.md 참고).

이미지에 포함된 기본 PHP 확장: pdo_mysql, pdo_pgsql, opcache, bcmath, exif, gd, gettext, intl, zip

개발

docker compose up -d                       # web(:8080)
docker compose exec web composer install   # vendor/ 가 없을 때
docker compose --profile xdebug up -d      # + Xdebug 가 켜진 web-xdebug (:8081)

MySQL 8.4·PostgreSQL 17 컨테이너는 주석으로 들어 있어 기본으로는 뜨지 않고, 앱은 .env.php 설정대로 접속합니다. 쓰려면 compose.yaml에서 MySQL·PostgreSQL 표시가 붙은 부분(environment의 DB_*·PGSQL_DB_*, depends_on, 서비스, volumes)의 주석을 푸세요.

주석을 푼 DB_*·PGSQL_DB_*는 .env.php보다 우선하므로, 컨테이너 안의 앱은 .env.php 내용과 관계없이 이 DB 컨테이너에 접속합니다. 포트는 127.0.0.1에만 열리며 FLEXAGON_HTTP_PORT·FLEXAGON_XDEBUG_PORT·FLEXAGON_MYSQL_PORT·FLEXAGON_PGSQL_PORT로 바꿀 수 있습니다.

사이트를 더 둘 때 — public/ 옆의 public_* 디렉터리가 사이트 하나입니다. application/은 공유하고, 각 디렉터리에 __flexagon.php·.htaccess·_entry.php·_prepare.php·_router.php를 둡니다(public/에서 복사). 사이트마다 컨테이너를 하나씩 띄우고 FLEXAGON_PUBLIC: public_admin처럼 지정합니다(compose.yaml의 admin 예시). 로컬에서는 포트로 나누되, 쿠키는 포트를 구분하지 않으므로 http://admin.localhost:8082처럼 호스트 이름도 달리 여세요.

배포 — 단계별 절차는 DEPLOY.md를 참고하세요.

docker build --target production -t myapp .
docker run -p 8080:8080 -e DB_HOST=... -e DB_PASSWORD=... myapp                 # public/
docker run -p 8080:8080 -e FLEXAGON_PUBLIC=public_admin -e DB_HOST=... myapp    # public_admin/
  • 비밀 값은 플랫폼의 Secret 기능으로 환경변수에 넣습니다. .dockerignore가 .env.php·.env를 빌드에서 빼므로 이미지에는 들어가지 않습니다.
  • 이미지 하나로 사이트 수만큼 서비스를 띄우고 FLEXAGON_PUBLIC만 다르게 줍니다. 사이트마다 DB 계정·확장·네트워크 노출(관리자 사이트는 내부망만 등)을 따로 정할 수 있습니다.
  • 스테이지(alpha·beta·production)마다 --target으로 이미지를 따로 빌드하므로 myapp:1.0.0-beta처럼 태그로 구분하세요.
  • 빌드는 호스트의 vendor/를 쓰지 않고 composer.lock대로 컨테이너 안에서 새로 설치합니다. 프로젝트 안의 path 저장소(./packages/...)도 함께 설치됩니다.
  • 세션은 암호화된 쿠키라 인스턴스를 늘려도 공유 저장소가 필요 없습니다. 모든 인스턴스에 같은 SESSION_ENCRYPTION_STRING을 주세요.
  • 컨테이너 파일시스템은 재시작하면 사라집니다. SQLite·업로드 파일은 운영에서 쓰지 말고 관리형 DB·오브젝트 스토리지를 쓰세요.
  • 읽기 전용 루트 파일시스템으로 띄울 때는 /var/run/apache2와 /tmp에 tmpfs를 붙입니다.
  • Apache 프로세스 수(MaxRequestWorkers)는 시작할 때 컨테이너 메모리 한도로 정합니다. (한도 − 64MB) ÷ 48MB이고 최소 2, 최대 256입니다(512MB → 9, 1GB → 20, 2GB → 41). 요청이 메모리를 많이 쓰면 APACHE_WORKER_MEMORY_MB를 올리고, 직접 정하려면 APACHE_MAX_REQUEST_WORKERS를 줍니다. 한도를 넘는 요청은 거절되지 않고 대기합니다. Cloud Run처럼 인스턴스당 동시 요청 수를 정하는 플랫폼에서는 그 값을 프로세스 수에 맞추세요. 프로세스는 1000번 연결하면 교체됩니다(APACHE_MAX_CONNECTIONS_PER_CHILD).