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).