재인쇄: http://dockone.io/article/117
[편집자 주] 이 글의 저자 Geoffrey는 DevOps와 Docker를 좋아하는 PHP 웹 개발자입니다. 이 기사에서는 Docker를 사용하여 PHP 개발 환경을 구축하는 방법을 주로 소개하고, Docker 기반 개발 환경을 구축하기 위해 단일 컨테이너를 사용할지, 아니면 다중 컨테이너를 사용할지, 그리고 각각의 장단점에 대해 설명합니다. PHP 개발자에게 읽기를 권장합니다.
현재 많은 개발자가 Vagrant를 사용하여 가상 머신 개발 환경을 관리하고 있습니다. Vagrant는 정말 멋지지만 많은 단점도 있습니다(가장 중요한 점은 리소스를 너무 많이 차지한다는 점입니다). 컨테이너 기술, Docker 및 Docker와 유사한 기술이 등장한 후 이 문제를 해결하는 것은 간단해졌습니다.
면책조항
boot2docker 작동 방식으로 인해 이 문서에 설명된 방법이 사용자 환경에서 제대로 작동하지 않을 수 있습니다. Linux가 아닌 환경에서 Docker 컨테이너에 폴더를 공유해야 하는 경우 추가 세부 사항에 주의해야 합니다. 실제로 발생한 문제를 소개하기 위해 후속 기사를 구체적으로 작성하겠습니다.
좋은 개발 환경이란 무엇인가?
먼저 좋은 개발 환경이 무엇인지 알아야 합니다. 나에게 있어서 좋은 개발 환경은 다음과 같은 특성을 갖추어야 합니다.
에서 사용할 수 있습니다. 할 것이다. 마음대로 삭제하고 새로운 환경을 만들 수 있어야 합니다.
빠른 시작. 내가 작업하고 싶을 때 즉시 작동합니다.
업데이트가 쉽습니다. 우리 업계에서는 상황이 매우 빠르게 움직이고 변화하므로 개발 환경을 새로운 소프트웨어 버전으로 업데이트하는 것이 쉬워야 합니다.
Docker는 위의 모든 기능과 그 이상을 지원합니다. 컨테이너를 거의 즉시 삭제하고 재구축할 수 있으며, 환경을 업데이트하려면 현재 사용 중인 이미지만 재구축하면 됩니다.
PHP 개발 환경이란 무엇인가요?
현재 웹 애플리케이션은 복잡하며, PHP 개발 환경은 환경의 단순성을 보장하기 위해 많은 것을 요구합니다.
이번에는 Nginx, PHP5-FPM, MySQL을 사용하여 Synmfony 프로젝트를 실행합니다. 컨테이너에서 명령줄을 실행하는 것은 더 복잡하므로 이 부분은 다음 블로그에 맡기겠습니다.
애완동물과 소
우리가 논의하고 싶은 또 다른 핵심 사항은 개발 환경을 여러 컨테이너에 배포해야 하는지 아니면 단일 컨테이너에 배포해야 하는지입니다. 두 방법 모두 장점이 있습니다.
단일 컨테이너는 배포 및 유지 관리가 쉽습니다. 독립적이기 때문에 모든 것이 가상 머신과 같은 동일한 컨테이너에서 실행됩니다. 그러나 이는 내부의 무언가(예: 새 버전의 PHP)를 업그레이드하려는 경우 전체 컨테이너를 다시 빌드해야 함을 의미하기도 합니다.
여러 컨테이너는 구성 요소를 추가할 때 더 나은 모듈성을 제공합니다. 각 컨테이너에는 웹, PHP, MySQL 등 스택의 일부가 포함되어 있으므로 모든 것을 다시 빌드할 필요 없이 각 서비스를 독립적으로 확장하거나 추가할 수 있습니다.
게으른데다가 노트에 뭔가 다른 것을 넣어야 하기 때문에 여기서는 단일 컨테이너 방식만 소개합니다.
프로젝트 초기화
가장 먼저 할 일은 새로운 Symfony 프로젝트를 초기화하는 것입니다. Composer의 create-project 명령을 사용하는 것이 좋습니다. 워크스테이션에 Composer를 설치하는 것도 가능했을 텐데, 그건 너무 간단했습니다. 이번에는 Docker를 통해 사용합니다.
이전에 Docker 명령에 대한 기사를 게시했습니다: make docker 명령(알겠습니다, 거짓말을 했습니다. 원래 이 기사에 썼는데, 분리하는 것이 더 나을 것이라고 생각했습니다).
어쨌든 읽어보셔도 됩니다. 다음으로, 아직 작곡가 명령이 없다면 자신만의 작곡가 별칭을 만들 수 있습니다.
$ alias composer="docker run -i -t -v $PWD:/srv ubermuda/composer"
이제 Symfony 프로젝트를 초기화할 수 있습니다.
$ 작곡가 create-project Symfony/framwork-standard- 에디션 SomeProject
멋져요! 이제 실제 작업이 시작됩니다. (블로거가 즐겨 먹던 발라블라 한 무리 생략.... 원문: 훌륭합니다. 하이파이브를 하고, 커피 한 잔을 마시거나 원하는 액상 약물을 마시고 실제 작업을 준비하세요. )
컨테이너
일반적으로 사용되는 Nginx, PHP5-FPM 및 MySQL-Server만 설치하고 사전 설치만 하면 표준 Symfony 프로젝트를 실행하는 자급자족형 컨테이너를 구축하는 것은 매우 쉽습니다. 준비된 Nginx 가상 호스트 구성 파일을 넣고 일부 구성 파일을 복사하면 완료됩니다.
이 컨테이너의 소스 코드는 GitHub의 ubermuda/docker-symfony 저장소에서 찾을 수 있습니다. Dockerfile은 Docker가 이미지를 빌드하는 데 사용하는 구성 파일입니다.
FROM debian:wheezy
ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -y
RUN apt-get install -y nginx php5-fpm php5-mysqlnd php5-cli mysql-server 감독자
RUN sed -e 's/;daemonize = yes/daemonize = no/' -i /etc/php5/fpm/php-fpm.conf
RUN sed -e 's/;listen.owner/listen.owner/' -i /etc/php5/fpm/pool.d/www.conf
RUN sed -e 's/;listen.group/listen .group/' -i /etc/php5/fpm/pool.d/www.conf
RUN echo "ndaemon off;" >> /etc/nginx/nginx.conf
vhost.conf / 추가 etc/nginx/sites-available/default
supervisor.conf /etc/supervisor/conf.d/supervisor.conf 추가
init.sh /init.sh
EXPOSE 80 3306
볼륨 추가 [ "/srv"]
WORKDIR /srv
CMD ["/usr/bin/supervisord"]
debian:wheezy 기본 이미지를 확장한 다음 Nginx 및 PHP5-FPM을 구성합니다.
RUN sed -e 's/;daemonize = yes/daemonize = no/' -i /etc/php5/fpm/php-fpm.conf
RUN sed -e 's/;listen.owner/listen .owner/' -i /etc/php5/fpm/pool.d/www.conf
RUN sed -e 's/;listen.group/listen.group/' -i /etc/php5/fpm/pool .d/www.conf
RUN echo "ndaemon off;" >> /etc/nginx/nginx.conf
여기서 두 가지 작업을 수행해야 합니다. 먼저 감독자가 추적할 수 있도록 PHP5-FPM 및 Nginx를 포그라운드에서 실행하도록 구성합니다.
그런 다음 지정된 사용자로 웹 서버를 실행하고 파일 권한을 처리하도록 PHP5-FPM을 구성합니다.
다음으로 구성 파일 세트를 설치해야 합니다. 첫 번째는 Nginx 가상 호스트 구성 파일 vhost.conf입니다:
server {
listening 80;
server_name _;
access_log / var/log/ nginx/access.log;
error_log /var/log/nginx/error.log;
root /srv/web;
index app_dev.php;
위치 / {
try_files $uri $uri/ /app_dev.php?$query_string;
}
위치 ~ [^/].php(/|$) {
fastcgi_pass unix:/var/run/php5-fpm .sock; Fastcgi_params 포함
}
}
도메인 이름이 필요하지 않기 때문에 server_name을 /svr/web의 경우로 설정하고 /srv 아래에 애플리케이션을 배포합니다. 나머지는 표준 Mginx + PHP5-FPM 구성입니다.
컨테이너는 한 번에 하나의 프로그램만 실행할 수 있으므로 Supervisord(또는 다른 프로세스 관리자가 있지만 저는 Supervisord를 선호합니다)가 필요합니다. 운 좋게도 이 프로세스 관리자는 필요한 모든 프로세스를 생성합니다! 다음은 감독자 구성의 짧은 섹션입니다.
[supervisord]
nodaemon=true
[program:nginx]
command=/usr/sbin/nginx
[program:php5-fpm ]
명령=/usr/sbin/php5-fpm
[program:mysql]
command=/usr/bin/mysqld_safe
[program:init]
command=/init.sh
autorestart=false
redirect_stderr=true
redirect_stdout=/srv/app/logs/init.log
여기서 해야 할 일은 모든 서비스를 정의하고 특수 프로그램인 init 프로세스를 추가하는 것입니다. 실제 서비스는 아니지만 시작 스크립트를 실행하는 독창적인 방법입니다.
이 시작 스크립트의 문제점은 일반적으로 먼저 시작하려면 일부 서비스가 필요하다는 것입니다. 예를 들어 일부 데이터베이스 테이블을 초기화하려고 할 수 있지만 MySQL을 먼저 실행하는 경우에만 가능합니다. 가능한 해결책은 시작 스크립트에서 MySQL을 시작한 다음 테이블을 초기화하여 감독자의 프로세스 관리에 영향을 미치지 않도록 하는 것입니다. MySQL을 중지하고 마지막으로 Supervisord를 시작해야 합니다.
이러한 스크립트는 다음과 유사합니다.
/etc/init.d/mysql start
app/console 교리:schema:update --force
/etc/init.d/mysql stop
exec /usr/bin/supervisord
보기 흉해 보입니다. 메소드를 변경하고 감독자가 실행하도록 하고 다시 시작하지 않도록 합시다.
실제 init.sh 스크립트는 다음과 같습니다:
#!/bin/bash
RET=1
while [[ RET -ne 0 ]]; sleep 1;
mysql -e 'exit' > /dev/null 2>&1; RET=$?
완료
DB_NAME=${DB_NAME:-symfony}
mysqladmin -u root create $DB_NAME
if [ -n "$INIT" ]; then
/srv/$INIT
fi
스크립트는 먼저 MySQL이 시작될 때까지 기다린 다음 환경 변수 DB_NAME(기본값은 Symfony)에 따라 DB를 생성합니다. 를 누른 다음 INIT 환경 변수에서 원하는 값을 찾습니다. 스크립트를 실행하고 실행해 보세요. 이 문서의 끝부분에서는 이러한 환경 변수를 사용하는 방법을 설명합니다.
이미지 빌드 및 실행
모든 것이 준비되었습니다. 필요한 것은 동풍뿐입니다. 또한 docker build 명령(
$ cd docker-symfony
$ docker build -t Symfony
)을 사용하여 Symfony Docker 이미지를 빌드해야 합니다.
이제 이를 사용하여 Symfony 프로젝트를 실행할 수 있습니다.
$ cd SomeProject
$ docker run -i -t -P -v $PWD:/srv Symfony
이 일련의 옵션이 수행하는 작업을 살펴보겠습니다.
-i 대화형 시작(대화형) 즉, STDIO(표준 입력 및 출력)가 현재 터미널에 연결됩니다. 이는 로그를 수신하거나 프로세스에 신호를 보내려는 경우에 유용합니다.
-t는 컨테이너에 대한 가상 TTY를 생성합니다. 이는 -i의 좋은 친구이며 일반적으로 함께 사용됩니다.
-P는 Docker 데몬에게 지정된 모든 포트(이 경우 포트 80)를 게시하도록 지시합니다.
-v $PWD:/srv 현재 디렉터리를 컨테이너의 /srv 디렉터리에 마운트합니다. 디렉토리를 마운트하면 대상 마운트 지점에서 디렉토리 내용을 사용할 수 있습니다.
앞서 언급한 DB_NAME 및 INIT 환경 변수가 환경을 사용자 정의하는 데 사용되는 이유를 기억하실 것입니다. 기본적으로 docker run의 -e 옵션을 통해 컨테이너에 환경 변수를 설정할 수 있습니다. 시작 스크립트는 환경 변수를 가져옵니다. 따라서 DB 이름이 some_project_dev인 경우 다음과 같이 컨테이너를 실행할 수 있습니다.
$ docker run - i -t -P -v $PWD:/srv -e DB_NAME=some_project_dev Symfony
INIT 환경 변수는 훨씬 더 강력하여 시작 시 지정된 스크립트를 실행할 수 있습니다.예를 들어, 작곡가 설치 명령을 실행하고 데이터베이스 스키마를 설정하는 bin/setup 스크립트가 있습니다:
#!/bin/bash
composer install
app/console 교리:schema:update --force
-e를 사용하여 실행하세요.
$ docker run -i -t -P
-v $PWD:/srv
-e DB_NAME=some_project_dev
-e INIT=bin/setup
참고로 -e 옵션은 docer run에서 여러 번 사용할 수 있는데 이는 매우 멋져 보입니다. 또한 시작 스크립트에는 실행 권한(chmod +x)이 필요합니다.
이제 모든 것이 예상대로 작동하는지 확인하기 위해 컬을 통해 컨테이너에 요청을 보냅니다. 먼저 Docker가 컨테이너의 포트 80에 매핑하는 공용 포트를 가져와야 합니다. docker port 명령을 사용하세요.
$ docker port $(docker ps -aql 1) 80
0.0.0.0:49153
docker ps -aql 1은 마지막 컨테이너의 ID를 쉽게 검색할 수 있는 유용한 명령입니다. 이 예에서 Docker는 컨테이너의 포트 80을 포트 49153에 매핑합니다. 말려서 살펴보자.
$curl http://localhost:49153
이 파일에 접근할 수 없습니다. 자세한 내용은 app_dev.php를 확인하세요.
localhost에서 접근하지 못하는 경우(번역자 주: 컨테이너의 localhost) dev 컨트롤러를 사용하는 경우 Symfony에서 기본 오류 메시지가 표시됩니다. 이는 컨테이너 내부에서 컬 요청을 보내는 것이 아니기 때문에 전면 컨트롤러 web/app_dev.php에서 이 줄을 안전하게 제거할 수 있습니다.
// 이 검사는 실수로 프로덕션 서버에 배포된 디버그 프런트 컨트롤러에 대한 액세스를 방지합니다.
// 이를 제거하거나 확장하거나 더 정교한 것을 자유롭게 만드세요.
if (isset($ _SERVER['HTTP_CLIENT_IP'])
|| isset($_SERVER['HTTP_X_FORWARDED_FOR'])
|| !(in_array(@$_SERVER['REMOTE_ADDR'], array('127.0.0.1', 'fe80 ::1', '::1')) || php_sapi_name() === 'cli-server')
) {
header('HTTP/1.0 403 금지됨');
종료( '이 파일에 액세스할 수 없습니다. 자세한 내용은 '.basename(__FILE__).'을 확인하세요.');
}
이 줄은 로컬 호스트 외부에서 개발자 컨트롤러에 액세스하는 것을 방지합니다.
이제 컬링하거나 브라우저를 사용하여 http://localhost:49153/:
result.png
에 액세스하면 정상적으로 작동할 수 있습니다. 쉽습니다! 이제는 빠르게 환경을 시작하고 업데이트할 수 있지만 아직 개선이 필요한 부분이 많습니다.
원본 링크: Docker를 사용한 PHP 개발 환경(번역자: He Linchong 검토자: Guo Lei)
이상은 Docker 기반의 PHP 개발 환경을 다양한 측면에서 소개하고 있으며, PHP 튜토리얼에 관심이 있는 친구들에게 도움이 되기를 바랍니다.