Docker에서 nginx + php-fpm (CakePHP) + MySQL을 시작할 때까지의 길

개요


  • 완성 후 구축 후 이미지
  • 구축
  • 디렉토리 구성
  • nginx
  • php-fpm + CakePHP
  • MySQL

  • 망설이는 포인트

  • 완성 후의 구축 이미지





    흰색 빼기의 사각형은 docker 컨테이너. nginx, php-fpm, MySQL 컨테이너를 이용한다.
    파란색 사각형은 호스트 OS 디렉토리.
    포인트
    nginx와 php-fpm이 호스트 OS의 동일한 디렉토리를 마운트합니다.

    건설



    디렉토리 구성



    호스트 OS 측에서 본 설정 파일 등의 디렉토리 구성
    .
    ├── data
    ├── docker-compose.yml
    ├── nginx
    │   ├── Dockerfile
    │   └── default.conf
    └── phpfpm
        └── Dockerfile
    
    

    ■ data 디렉토리
     nginx와 php가 공통의 문서 루트를 이용하기 위해서 이용. 정적 파일을 nginx가 반환할 수 있도록 동일한 데이터를 볼 수 있도록 한다. nginx가 정적 파일을 반환 할 필요가 없다면 모든 요청을 php-fpm 측에 흘려 버리면 좋기 때문에 같은 위치를 마운트 할 필요는 없다.

    nginx



    docker-compose.yml
      nginx:
        build: ./nginx/
        ports:
          - 8080:80
        links:
          - phpfpm
        volumes:
          - ./data:/var/www/html
    

    Dockerfile
    FROM nginx:1.15.5-alpine
    COPY ./default.conf /etc/nginx/conf.d/default.conf
    

    ■volumes
    호스트 OS의 ./data 디렉토리를 문서 루트의 상위 디렉토리/var/www/html에 마운트합니다. (실제 문서 루트 디렉토리는 나중에 php 측에서 작성)

    default.conf
    server {
        listen 80;
        server_name _;
        root /var/www/html/myapp/webroot;
        index index.php
    
        access_log /var/log/nginx/access_log;
        error_log /var/log/nginx/error_log debug;
    
        location / {
            try_files $uri $uri/ /index.php$is_args$args;
        }
    
        location ~ \.php$ {
            fastcgi_split_path_info ^(.+\.php)(\.+)$;
            fastcgi_pass phpfpm:9000;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param PATH_INFO $fastcgi_path_info;
        }
    }
    
    

    이후의 순서로 myapp 프로젝트를 CakePHP로 작성한다. CakePHP는 myapp/webroot를 루트로 지정하도록 지시합니다.try_files 에서는, 왼쪽으로부터 순서대로 그 자원이 있는지 확인한다. 그렇지 않으면 CakePHP의 index.php에 요청합니다. 정적 콘텐츠가 있으면 nginx가 정적 콘텐츠를 반환합니다.

    포인트는 fastcgi_pass로 phpfpm:9000를 지정하는 것. 링크 덕분에 phpfpm을 nginx 컨테이너 내에서 이름 확인할 수 있습니다. (Hosts 파일이라든지 써주고 있을까?)

    php-fpm + CakePHP



    docker-compose.yml
      phpfpm:
        build: ./phpfpm/
        links:
          - mysql
        volumes:
          - ./data:/var/www/html
    

    Dockerfile
    FROM php:7.2.10-fpm-stretch
    RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \
        php -r "if (hash_file('SHA384', 'composer-setup.php') === '93b54496392c062774670ac18b134c3b3a95e5a5e5c8f1a9f115f203b75bf9a129d5daa8ba6a13e2cc8a1da0806388a8') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;" && \
        php composer-setup.php && \
        php -r "unlink('composer-setup.php');" && \
        mv composer.phar /usr/local/bin/composer && \
        apt-get update && \
        apt-get install -y libicu-dev && \
        docker-php-ext-install intl pdo_mysql mbstring && \
        apt-get install -y git && \
        apt-get install -y zip unzip && \
        composer config -g repos.packagist composer https://packagist.jp && \
        composer global require hirak/prestissimo
    

    Dockerfile에서는 composer의 셋업과 CakePHP용의 라이브러리(intl, pdo_mysql)를 인스톨 하고 있다. composer가 내부에서 git나 zip, unzip을 이용하고 있는 것 같기 때문에 인스톨 해 둔다.
    Dockerfile의 후반 2행은 composer 고속화 대응이므로, 삭제해도 문제 없다.

    컨테이너 시작 후/var/www/html/에 CakePHP 프로젝트를 만듭니다.
    composer create-project --prefer-dist cakephp/app myapp
    

    MySQL



    docker-compose.yml
      mysql:
        image: mysql:8.0.12
        environment:
          MYSQL_DATABASE: my_app
          MYSQL_USER: my_app
          MYSQL_PASSWORD: secret
          MYSQL_ROOT_PASSWORD: password   
    

    CakePHP의 기본 DB 설정 이름에 맞게 설정 값을 추가. MYSQL_ROOT_PASSWARD 는 불필요합니까?

    연결 확인



    호스트 OS에서 localhost:8080에 액세스


    망설이는 포인트



    CakePHP 프로젝트의 프로젝트가 컨테이너 시작시 지워집니다.



    docker-compose로 문서 루트를 마운트하면,
    1. 컨테이너 시작시
    2. 호스트 OS의 디렉토리 구성을 컨테이너에 마운트(덮어쓰기)합니다.

    Dockerfile로 만들어진 CakePHP의 프로젝트는 마운트시에 덮어쓰여져 없어진다.
    대응책으로서 CakePHP의 프로젝트는 컨테이너 기동 후 수동으로 작성했다.
    Dockerfile의 CMD를 사용하면 수동이 불필요하게 될 것 같다.

    정적 콘텐츠가 반환되지 않음



    nginx 컨테이너와 php 컨테이너에서 호스트 OS를 마운트하지 않았습니다. 그 때문에 CakePHP의 TOP 페이지를 액세스해도 css나 png와 같은 파일이 반환되지 않았다. 이유는 간단하고, nginx측 컨테이너에는 css, png등의 정적 파일이 존재하지 않기 때문에.
    말해 보면 당연하지만 곤란했다.
    nginx 컨테이너에서 php 컨테이너를 마운트하는 방법도 검토했지만 어떤 경로가 어떤 경로와 마운트되는지 잘 모르겠다.
    대응책으로서 호스트 OS의 디렉토리를 마운트해 CakePHP의 자원을 양쪽의 컨테이너로부터 액세스 할 수 있도록 했다.

    좋은 웹페이지 즐겨찾기