소개
Continuous Integration (CI) 및 Continuous Deployment (CD)는 현재 소프트웨어 개발에서 가장 인기 있는 주제 중 일부입니다. 소프트웨어 아키텍처의 CI/CD 측면을 달성하기 위해 개발자들은 컨테이너를 사용합니다. 컨테이너는 가볍고 가상화되었으며 이식성이 뛰어난 소프트웨어 정의 환경입니다. 컨테이너 내에서 소프트웨어는 물리적 호스트 머신에서 실행되는 다른 소프트웨어와 격리되어 실행될 수 있습니다. 이 튜토리얼의 초점은 컨테이너 플랫폼인 Docker를 사용하여 웹 애플리케이션을 배포하고 실행하는 데 있습니다. Docker는 웹 서버 스택의 설정 프로세스를 간소화하는 데 도움이 됩니다. 이 튜토리얼에서는 LEMP 스택을 사용하여 Laravel 애플리케이션을 서비스할 것입니다.
LEMP 스택은 운영 체제인 Linux, Nginx를 웹 서버로, MySQL을 데이터베이스로, 그리고 PHP를 스크립팅 및 동적 처리를 위한 언어로 결합합니다. 다음 Ubuntu에 LEMP 스택을 설치하고 구성하는 방법에 대한 튜토리얼을 따를 수 있습니다. Laravel은 웹 애플리케이션 개발을 위한 최고의 PHP 프레임워크 중 하나입니다.
Docker는 Docker Compose라는 도구를 제공하여 Docker 컨테이너의 설정 프로세스를 정의합니다. Docker Compose를 사용하면 개발자는 애플리케이션의 인프라, 서비스, 볼륨, 네트워크 및 모든 종속성을 docker-compose 파일이라는 하나의 파일에 정의할 수 있습니다. docker container create, docker container run 등과 같은 명령을 통해 여러 Docker 컨테이너를 관리할 수 있습니다.
이 튜토리얼에서는 Docker 컨테이너 내부에서 Nginx 및 MySQL을 사용하여 Laravel 웹 애플리케이션을 배포하는 방법을 배웁니다.전체 스택에 대한 구성은 PHP, MySQL 및 Nginx에 대한 다른 구성 파일뿐만 아니라 docker-compose 파일 내에 정의됩니다. 시작해 봅시다!
가장 먼저 해야 할 일
- 이 튜토리얼은 실습 위주로 진행되므로, 다음이 설치되어 있어야 합니다: Ubuntu 20.04을(를) 초기 운영 환경으로 사용해야 합니다. 또한 sudo 권한이 있는 non-root 사용자가 있어야 합니다. 다음은 Ubuntu 서버 설정을 도와주는 단계별 튜토리얼입니다..
- Docker를 설치해야 합니다. 다음은 관련 튜토리얼입니다: Ubuntu 18.04에서 Docker를 설치하고 작동하는 방법.
- 공식 Docker 문서의 튜토리얼을 따라 Docker Compose를 설치해야 합니다.
1단계: Laravel 다운로드 및 종속성 설치
첫 번째 단계는 저장소에서 Laravel 코드를 가져오는 것입니다. 실제 시나리오에서는 GitHub, Bit Bucket, Gitlab 등 어딘가의 저장소에 Laravel 코드가 있을 수 있습니다. 하지만 이 튜토리얼에서는 다음의 공식 Laravel 저장소에서 최신 버전을 복제할 것입니다: GitHub. 이 저장소에는 PHP용 애플리케이션 수준 종속성 관리자인 composer 파일이 포함되어 있습니다. 모든 것이 Docker 컨테이너 내부에서 실행되기를 원하므로, Docker의 composer 이미지를 사용하여 종속성을 설치할 것입니다. 이를 통해 실제 호스트 머신에 composer를 전역으로 설치할 필요가 없습니다. 다음으로, 터미널을 실행하세요.
홈 디렉터리로 이동합니다:
|
1 |
cd ~ |
다음 명령어를 입력하여 laravel-web이라는 디렉토리에 리포지토리를 복제합니다. 이름은 원하는 대로 자유롭게 지정할 수 있습니다. 이 리포지토리를 작성할 당시 이 명령어를 실행하면 Laravel 버전 8을 가져왔습니다. 여러분이 이 명령어를 실행할 때는 아마도 더 새로운 버전을 보게 될 것입니다:
|
1 |
git clone https://github.com/laravel/laravel.git laravel-web |
그런 다음, 방금 리포지토리를 복제한 디렉토리로 이동합니다:
|
1 |
cd ~/laravel-web |
다음 명령어를 입력하여 Docker의 composer 이미지를 사용해 laravel 앱에 필요한 디렉토리를 마운트합니다.:
|
1 |
docker run --rm -v $(pwd):/app composer install |
docker run 명령어의 -v 및 –rm 플래그는 삭제되기 전에 현재 디렉토리에 바인드 마운트될 임시 컨테이너를 생성합니다. 이 명령어는 ~/laravel-web의 콘텐츠를 컨테이너로 복사하고 composer에 의해 생성된 vendor 폴더가 현재 디렉토리로 다시 복사되도록 합니다.
이제 laravel-web 디렉토리의 소유권을 루트가 아닌(non-root) 사용자에게 변경해야 합니다. 이를 통해 다음 단계에서 루트가 아닌 사용자로 애플리케이션 코드를 작업하고 컨테이너 내부에서 프로세스를 실행할 수 있습니다. 소유권을 변경하려면 다음 명령어를 입력하십시오:
|
1 |
sudo chown -R $USER:$USER ~/laravel-web |
이제 애플리케이션 코드가 준비되었습니다. 디렉토리 소유권이 루트가 아닌 사용자에게 있으므로 docker-composer 파일에서 애플리케이션 서비스를 정의하는 단계를 진행할 수 있습니다.
2단계: Docker Compose 파일 생성
Docker Compose는 애플리케이션을 빌드하고 배포하는 과정을 간소화합니다. 구성과 서비스를 정의하고 나면, 애플리케이션 의존성에 대해 걱정할 필요 없이 Docker와 Docker Compose가 설치된 모든 호스트 머신에 애플리케이션을 쉽게 배포할 수 있습니다. 가장 중요한 것은 다음에서 볼 수 있듯이 단 하나의 Docker Compose 명령어로 이 작업을 수행할 수 있다는 점입니다: 9단계.
이 단계에서는 Laravel 앱을 배포하는 데 필요한 웹 서버, 데이터베이스 및 애플리케이션 서비스에 대한 구성이 포함된 Docker Compose 파일을 정의합니다.
Docker Compose 파일은 YAML 확장자로 저장되는 파일입니다. 유효한 Docker Compose 파일을 작성하려면 올바른 들여쓰기가 필수적입니다. 다음 명령어를 입력하여 nano 편집기로 파일을 생성하고 엽니다:
|
1 |
nano ~/laravel-web/docker-compose.yml |
다음으로, 이 파일에 app, webserver, db의 세 가지 서비스를 정의합니다. db 섹션은 애플리케이션의 데이터베이스 자격 증명을 정의하므로, 강력한 mysql_root_password를 선택하여 해당 섹션에서 변경해야 합니다. 다음 코드를 복사하여 붙여넣으세요:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
version: '2.0' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: cloudsigma.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www/html/ networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" networks: - app-network #MySQL Service db: image: mysql:5.7.32 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel_web MYSQL_ROOT_PASSWORD: replace_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql networks: - app-network #Docker Networks networks: app-network: driver: bridge |
아래는 위 코드의 서비스 정의에 대한 설명입니다:
- app: Laravel 애플리케이션을 정의하고, 다음 단계에서 정의할 커스텀 Docker 이미지인 cloudsigma.com/php를 실행합니다: 4단계. 또한 컨테이너 내의 working_dir을 /var/www/html로 설정합니다.
- webserver: Docker에서 nginx:alpine 이미지를 가져와 포트 80 및 443.
- db: mysql:5.7.32 이미지를 가져옵니다 Docker에서 가져오며 몇 가지 환경 변수를 정의합니다. 여기에는 다음과 같은 이름의 데이터베이스가 포함됩니다 라라벨 웹 애플리케이션 및 데이터베이스의 루트 비밀번호입니다. 원하는 이름으로 데이터베이스 이름을 변경할 수 있습니다. 다음을 교체하는 것을 잊지 마십시오. MySQL 루트 비밀번호 강력한 비밀번호를 가진 속성입니다. 이 서비스는 호스트의 3306 포트를 컨테이너의 3306 포트로 매핑하기도 합니다.
각 서비스의 container_name 속성은 서비스에 해당하는 컨테이너의 이름을 정의합니다. 이 속성을 정의하지 않으면 Docker는 각 컨테이너에 대해 임의의 이름을 선택합니다.
networks 속성은 다음을 정의합니다. 브리지 네트워크 app-network라고 불리며, 컨테이너 간의 통신을 원활하게 합니다. 브리지 네트워크는 동일한 네트워크 브리지에 있는 컨테이너 간의 통신만 허용하는 소프트웨어 브리지에 의해 제어됩니다. 브리지 소프트웨어 컨트롤러는 서로 다른 브리지 네트워크에 있는 컨테이너가 서로 직접 통신하지 못하도록 방지하는 드라이버를 설치합니다. 이는 관련 서비스만 직접 통신할 수 있으므로 높은 수준의 보안을 보장합니다. 관련 기능에 연결되는 여러 서비스와 네트워크를 정의하도록 선택할 수 있습니다.
3단계: 데이터 영속화 방법
귀하의 웹 애플리케이션은 사용자에게 데이터를 처리하고 제공하게 됩니다. 이 단계에서는 애플리케이션의 데이터를 보존하기 위해 서비스 정의에 볼륨 및 바인드 마운트를 정의하는 과정을 안내합니다. Docker는 다음과 같은 놀라운 기능을 제공합니다. 바인드 마운트 및 볼륨 데이터를 보존하고 애플리케이션 설정 파일을 저장하기 위한 것입니다. Docker를 사용하여 Laravel 앱을 설정할 때 이를 사용할 것입니다.
Volumes는 백업 제공 및 컨테이너의 수명 주기 이후의 데이터 보존을 포함한 다양한 이유로 선호됩니다. Bind Mounts는 보통 호스트 머신의 실제 디렉터리를 참조합니다. 볼륨을 생성하면 Docker의 스토리지 디렉터리 내부에 Docker가 관리하는 새 디렉터리가 생성됩니다. Bind Mount를 생성하면 호스트 머신 내부의 파일 또는 디렉터리가 컨테이너에 마운트됩니다(절대 경로로 참조됨). 이는 호스트 머신에서 코드를 변경하면 컨테이너에서 즉시 사용할 수 있게 되므로 웹 애플리케이션에 매우 중요합니다.
Bind Mounts를 사용할 때는 주의해야 합니다. Docker 컨테이너 내부에서 실행되는 프로세스는 호스트 파일 시스템을 변경할 수 있으며 호스트 시스템에서 실행 중인 non-Docker 프로세스에 영향을 미칠 수 있습니다. Docker 마운트는 강력한 기능이지만 이러한 보안상의 영향을 유의해야 합니다.
그렇다면 이제 설정에서 이 두 가지 기능을 어떻게 사용할 수 있는지 알아보겠습니다. 먼저, MySQL 데이터베이스를 보존하기 위한 볼륨을 정의하겠습니다. 우리가 생성한 Docker Compose 파일에서, 아래에 강조된 것처럼 db 서비스 아래에 volumes 속성을 추가합니다:
|
1 2 3 4 5 6 7 8 |
#MySQL Service db: ... volumes: - dbdata:/var/lib/mysql/ networks: - app-network ... |
정의된 대로, dbdata 볼륨은 /var/lib/mysql의 내용을 영구적으로 보존합니다. 이는 백업을 용이하게 하고 데이터를 잃지 않고 서비스를 재시작할 수 있도록 합니다. 다음으로, 여러 서비스에서 사용할 수 있도록 Docker Compose 파일 끝에 volumes 정의를 추가해야 합니다. 파일 하단에 다음 코드 스니펫을 입력하세요:
|
1 2 3 4 |
#Volumes volumes: dbdata: driver: local |
MySQL 데이터베이스에 연결하려면 자격 증명을 제공해야 합니다. 이를 위해 volumes 속성 아래의 db 서비스에 강조 표시된 다음 코드 스니펫을 추가하여 바인드 마운트를 정의하세요:
|
1 2 3 4 5 6 7 |
#MySQL Service db: ... volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf ... |
이 코드는 컨테이너 내의 ~/laravel-web/mysql/my.cnf를 /etc/mysql/my.cnf에 바인딩합니다. 바인딩된 파일은 다음에서 생성할 MySQL 설정 파일입니다: 7단계.
컨테이너는 애플리케이션 코드를 서비스하기 위해 Nginx 서버를 사용해야 합니다. 따라서 이 목적을 위해 webserver 서비스 아래에 두 개의 바인드 마운트(Nginx 설정 파일용 하나, 애플리케이션 코드용 하나)를 정의할 것입니다. webserver 서비스 아래에 volumes 정의를 위한 다음 코드 스니펫을 추가하세요:
|
1 2 3 4 5 6 7 8 |
#Nginx Service webserver: ... volumes: - ./:/var/www/html/ - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network |
이 라인 – ./:/var/www/html은 ~/laravel-web 디렉터리의 애플리케이션 코드를 컨테이너 내부의 /var/www/html 디렉터리에 바인딩합니다. 두 번째 바인드 마운트의 경우, Nginx 설정 파일이 ~/laravel-web/nginx/conf.d/에 생성됩니다. 이 파일은 컨테이너 내부의 /etc/nginx/conf.d/에 마운트됩니다. 따라서 필요한 경우 호스트 머신에서 설정 파일을 업데이트할 수 있습니다. Nginx conf 파일은 다음에서 생성할 것입니다: 6단계.
코드 변경 사항이 컨테이너에 자동으로 반영되도록 하기 위해 애플리케이션 코드를 컨테이너에 바인드 마운트합니다. 이는 배포 프로세스의 속도를 높여줍니다. 따라서 app 서비스에 다음과 같이 강조된 코드 스니펫을 추가합니다:
|
1 2 3 4 5 6 7 8 |
#PHP Service app: ... volumes: - ./:/var/www/html/ - ./php/laravel.ini:/usr/local/etc/php/conf.d/laravel.ini networks: - app-network |
두 번째 줄은 php 설정 파일을 바인딩하며, 이 파일은 5단계에서 생성할 ~/laravel-web/php/laravel.ini 파일 내부를 컨테이너 내부의 /usr/local/etc/php/conf.d/laravel.ini로 바인딩합니다.
이제 전체 Docker Compose 파일은 다음과 같아야 합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
version: '2.0' services: #PHP Service app: build: context: . dockerfile: Dockerfile image: cloudsigma.com/php container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www/html/ volumes: - ./:/var/www/html/ - ./php/laravel.ini:/usr/local/etc/php/conf.d/laravel.ini networks: - app-network #Nginx Service webserver: image: nginx:alpine container_name: webserver restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www/html/ - ./nginx/conf.d/:/etc/nginx/conf.d/ networks: - app-network #MySQL Service db: image: mysql:5.7.32 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laravel_web MYSQL_ROOT_PASSWORD: replace_mysql_root_password SERVICE_TAGS: dev SERVICE_NAME: mysql volumes: - dbdata:/var/lib/mysql/ - ./mysql/my.cnf:/etc/mysql/my.cnf networks: - app-network #Docker Networks networks: app-network: driver: bridge #Volumes volumes: dbdata: driver: local |
모든 것이 올바르게 보인다면, Ctrl + O를 눌러 파일을 저장합니다. 그런 다음, Ctrl + X를 눌러 편집기를 종료합니다. 이 시점에서 Docker Compose 파일을 사용하여 애플리케이션을 위한 사용자 정의 Docker 이미지를 빌드할 수 있어야 합니다.
4단계: Dockerfile 생성
Dockerfile에는 Docker가 사용자 정의 Docker 이미지를 빌드하는 데 사용할 수 있는 지침이 포함되어 있습니다. 또한 필요한 소프트웨어를 설치하고 애플리케이션에 필요한 설정을 구성할 수도 있습니다. 이는 애플리케이션 코드를 호스팅할 컨테이너 내부의 환경을 지정합니다. 생성한 이미지를 공유하기 위해 docker hub에 푸시하거나 다른 프라이빗 레지스트리에 저장할 수 있습니다.
Laravel 애플리케이션 이미지를 빌드하기 위한 지침을 지정하는 Dockerfile을 생성하겠습니다. nano를 사용하여 ~/laravel-web 디렉토리에 Dockerfile을 생성합니다:
|
1 |
nano ~/laravel-web/Dockerfile |
열린 편집기에 다음 코드를 추가합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
FROM php:7.4-fpm # Copy composer.lock and composer.json into the working directory COPY composer.lock composer.json /var/www/html/ # Set working directory WORKDIR /var/www/html/ # Install dependencies for the operating system software RUN apt-get update && apt-get install -y \ build-essential \ libpng-dev \ libjpeg62-turbo-dev \ libfreetype6-dev \ locales \ zip \ jpegoptim optipng pngquant gifsicle \ vim \ libzip-dev \ unzip \ git \ libonig-dev \ curl # Clear cache RUN apt-get clean && rm -rf /var/lib/apt/lists/* # Install extensions for php RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl RUN docker-php-ext-configure gd --with-freetype --with-jpeg RUN docker-php-ext-install gd # Install composer (php package manager) RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Copy existing application directory contents to the working directory COPY . /var/www/html # Assign permissions of the working directory to the www-data user RUN chown -R www-data:www-data \ /var/www/html/storage \ /var/www/html/bootstrap/cache # Expose port 9000 and start php-fpm server (for FastCGI Process Manager) EXPOSE 9000 CMD ["php-fpm"] |
Dockerfile은 먼저 php:7.4-fpm Docker 이미지를 기반으로 이미지를 생성합니다. 이는 PHP FastCGI 구현(PHP-FPM이(가) 설치됩니다. Laravel이 올바르게 작동하려면 mcrypt, pdo_mysql, mbstring 및 imagick과 같은 다른 php 확장 프로그램이 사용 가능해야 하며, 스크립트가 이를 설치합니다. 그런 다음 composer php 패키지 관리자입니다. 컨테이너는 이를 사용하여 Laravel php 의존성을 설치합니다.
RUN 지시어를 사용하여 컨테이너 내부에서 설치, 업데이트 및 설정 구성과 같은 명령을 정의할 수 있습니다. 또한 사용자 권한도 할당합니다. WORKDIR 지시어는 작업 디렉터리를 지정하며, 이 경우에는 /var/www/html입니다. 스크립트는 CHOWN 명령을 실행하여 /var/www/html 디렉터리 권한을 www-data 사용자에게 할당합니다.
최종적으로 이미지를 빌드하기 전에 컨테이너 내부에서 실행 중인 애플리케이션에 대한 액세스를 허용하도록 포트를 노출해야 합니다. EXPOSE 명령은 php-fpm 서버를 위해 9000번 포트를 노출합니다. 실행할 마지막 명령은 CMD 지시어입니다. 이는 php-fpm을 실행하여 서버를 시작합니다.
이제 Ctrl + O를 눌러 파일을 저장할 수 있습니다. 그런 다음 Ctrl + X를 눌러 편집기를 종료합니다.
5단계: PHP 구성
이 단계에서는 Nginx로부터 들어오는 요청을 처리하도록 php 서비스를 구성합니다. php 디렉터리 내에 laravel.ini 파일을 생성합니다. 이 파일은 PHP 구성을 저장합니다. 이 파일은 컨테이너의 /usr/local/etc/php/conf.d/laravel.ini에 바인드 마운트한 파일로, 3단계에서 수행했습니다. 이 파일의 구성은 PHP가 시작할 때 일반적으로 읽는 기본 php.ini 파일을 덮어씁니다. php 디렉터리를 생성하려면 다음 명령을 입력하십시오:
|
1 |
mkdir ~/laravel-web/php |
다음 명령어를 입력하여 php 디렉토리 내에 laravel.ini 파일을 생성하고 엽니다:
|
1 |
nano ~/laravel-web/php/laravel.ini |
기본 php.ini 파일은 업로드 제한이 2M로 설정되어 있습니다. 예를 들어, 더 큰 파일을 업로드하려는 경우를 위해 허용된 업로드 제한 값을 변경하여 php 설정을 조정하고 설정하는 방법을 보여드리겠습니다. 파일 내에 다음 코드 줄을 입력하십시오:
|
1 2 |
upload_max_filesize=80M post_max_size=80M |
이렇게 하면 업로드 제한이 설정되며 총 크기가 80MB 이하인 파일을 업로드할 수 있습니다. 기본 php 설정을 재정의하기 위해 laravel.ini 파일 내에 다른 php 설정을 추가할 수 있습니다. 이제 파일을 저장하고 닫습니다.
Step 6: Configure Nginx
이 단계에서는 앞서 정의한 php 서비스를 사용하도록 Nginx를 구성합니다. Nginx는 PHP-FPM을 FastCGI server로 사용하여 동적 콘텐츠를 제공합니다. FastCGI 서버는 대화형 프로그램이 웹 서버와 인터페이스할 수 있도록 지원하는 소프트웨어입니다.
앞서 docker-compose 파일의 Step 3에서 정의한 대로, ~/laravel-web/nginx/conf.d/ 디렉토리 내에 Nginx 구성 파일인 app.conf를 생성할 것입니다. 먼저, 다음 명령어를 입력하여 디렉토리를 생성합니다:
|
1 |
mkdir -p ~/laravel-web/nginx/conf.d |
다음으로, 다음 명령어를 입력하여 nano를 사용해 app.conf 파일을 생성하고 엽니다:
|
1 |
nano ~/laravel-web/nginx/conf.d/app.conf |
파일에 다음 Nginx 구성 코드를 추가합니다:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
server { listen 80; index index.php index.html; error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; root /var/www/html/public; location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass app:9000; fastcgi_index index.php; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; } location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } } |
Nginx는 URL을 기반으로 웹사이트 방문자에게 어떤 디렉토리를 제공해야 하는지 알기 위해 서버 블록이라고 불리는 구성 파일을 읽습니다. 자세한 내용은 저희의 'Ubuntu에 Nginx 설치하기' 튜토리얼에서 서버 블록을 설정하는 방법을 참고하십시오. 18.04. 정의된 지시문은 다음과 같은 용도로 사용됩니다:
- listen – 서버가 들어오는 요청을 대기할 포트를 정의하며, 일반적으로 80번 포트입니다.
- error_log & access_log – 애플리케이션 로그를 기록할 파일을 정의합니다.
- root – 인터넷에서 서버로 들어오는 모든 요청을 처리할 디렉터리인 웹 루트(webroot) 경로를 정의합니다.
php의 location 블록에서 fastcgi_pass 지시문은 app 서비스가 9000번 포트의 TCP 소켓에서 대기하고 있음을 지정합니다(이는 Dockerfile에 정의되어 있습니다). 이는 PHP-FPM 서버가 Unix 소켓이 아닌 네트워크를 통해 대기하도록 지시합니다. Unix 소켓은 TCP 소켓보다 속도 면에서 약간의 이점이 있을 수 있지만, 네트워크 프로토콜이 없기 때문에 네트워크 스택을 건너뜁니다.
Unix 소켓은 호스트가 단일 머신에 위치한 시나리오에 더 적합합니다. 그러나 서로 다른 호스트에서 서비스가 실행 중인 경우, TCP 소켓은 분산된 서비스를 연결할 수 있다는 장점이 있습니다. 우리의 경우, app 컨테이너는 웹 서버 컨테이너와 다른 호스트에서 실행되고 있습니다. 따라서 우리의 구성에는 TCP 소켓이 가장 적합합니다.
이제 Ctrl + O를 눌러 파일을 저장한 다음, Ctrl + X를 눌러 편집기를 종료할 수 있습니다. nginx/conf.d/ 디렉터리에서 변경한 사항은 다음 단계의 Docker Compose 파일에 추가한 바인드 마운트 덕분에 웹 서버 컨테이너에 자동으로 반영됩니다: 3단계.
7단계: MySQL 구성
Nginx가 PHP와 작동하도록 구성한 후, 이제 PHP에 동적 데이터를 저장하고 제공하도록 MySQL을 구성할 수 있습니다. 우리는 이미 PHP와 MySQL 통신에 필요한 확장을 설치하도록 Docker Compose 파일을 설정했습니다. 우리는 mysql 폴더 내에 MySQL 구성 파일인 my.cnf를 생성할 것이며, 이는 Docker Compose의 db 서비스 섹션에서 정의한 3단계.
MySQL 구성 설정 및 변경 사항은 원할 때마다 my.cnf 파일에 적용할 수 있습니다. 이는 컨테이너 내부에 즉시 반영되어야 합니다. 먼저 다음 명령어를 입력하여 디렉터리를 생성합니다:
|
1 |
mkdir ~/laravel-web/mysql |
다음으로, 다음 명령어를 입력하여 nano를 생성하고 엽니다:
|
1 |
nano ~/laravel-web/mysql/my.cnf |
쿼리 로그를 활성화하고 쿼리 로그 파일 위치를 지정하려면 다음 코드 스니펫을 입력합니다:
|
1 2 3 |
[mysqld] general_log = 1 general_log_file = /var/lib/mysql/general.log |
general_log 속성을 1로 정의하면 일반 로그가 허용됩니다. general_log_file 속성은 로그 파일의 위치를 지정합니다. Ctrl + O를 눌러 파일을 저장한 다음, Ctrl + X를 눌러 편집기를 종료합니다.
8단계: Laravel 환경 변수 설정
여기까지 모든 서비스와 구성 설정이 완료되었습니다. 따라서 컨테이너를 배포할 수 있습니다. 하지만 웹 애플리케이션을 실제로 사용하기 전에 완료해야 하는 중요한 단계가 있습니다. 바로 환경 변수입니다. Laravel 프레임워크는 환경을 정의하는 데 사용하는 .env라는 파일을 필요로 합니다. 기본적으로 Laravel에는 .env로 복사한 다음 실제 세부 정보로 변수를 수정할 수 있는 .env.example이 제공됩니다. 다음 명령어를 입력하여 파일을 복사합니다:
|
1 |
cp .env.example .env |
복사가 완료되면 nano를 사용하여 파일을 열고 수정합니다:
|
1 |
nano .env |
다음은 파일이 어떻게 보일 수 있는지 보여주는 스크린샷입니다:

파일에서 다음 단계는 지금까지 수행한 이전 구성에서 설정한 대로 DB_CONNECTION 블록 아래의 변수를 수정하는 것입니다. 다음과 같이 업데이트합니다:
- DB_HOST 은(는) db 데이터베이스 컨테이너입니다.
- DB_DATABASE 은(는) laravel_web.
- DB_USERNAME 은(는) 데이터베이스의 사용자 이름입니다. 원하는 이름을 선택하되, 이 튜토리얼에서는 다음으로 진행하겠습니다: laraveldocker.
- DB_PASSWORD 은(는) 위의 사용자가 데이터베이스에 로그인하는 데 사용할 강력한 비밀번호이므로 강력한 비밀번호를 선택하세요. 10단계에서 여기에서 선택한 비밀번호로 이 사용자를 생성합니다.
값이 업데이트되면 DB_CONNECTION은 다음과 같이 보여야 합니다:

파일을 저장하고 닫습니다.
9단계: Docker 컨테이너 실행
이 단계에서는 모든 서비스와 구성이 Docker Compose 파일에 정의되어 있습니다. 모든 컨테이너를 시작하고, 볼륨을 생성하고, 네트워크를 연결하고, 애플리케이션을 설정 및 빌드하는 데는 단 하나의 명령어만 필요합니다. 터미널에 다음 명령어를 입력하세요:
|
1 |
docker-compose up -d |
처음으로 docker-compose up 명령어를 실행하면 필요한 모든 Docker 이미지를 다운로드합니다. 로컬 컴퓨터에 인프라를 설정하는 경우 완료하는 데 시간이 다소 걸릴 수 있습니다. 이미지가 다운로드되면 Compose가 컨테이너를 생성합니다. -d 플래그는 Docker가 백그라운드에서 컨테이너를 실행하도록 지시합니다. 프로세스가 성공적으로 완료되면 터미널에 다음과 같은 화면이 표시됩니다:

실행 중인 모든 컨테이너를 나열하려면 터미널에 다음 명령어를 입력하세요:
|
1 |
docker ps |
아래 스크린샷과 같이 app, webserver, db 컨테이너에 대한 세부 정보가 표시되어야 합니다:

- CONTAINER ID – 각 컨테이너의 고유 식별자입니다.
- NAMES – Docker Compose 파일에 정의된 각 컨테이너와 관련된 서비스 이름입니다. (컨테이너에 액세스하려면 컨테이너 ID 또는 이름 중 하나를 사용할 수 있습니다).
- IMAGE – 각 컨테이너의 이미지 이름입니다.
- STATUS – 컨테이너의 상태에 대한 정보를 표시합니다 (중지됨, 실행 중 또는 재시작 중일 수 있습니다).
- PORTS – 컨테이너가 노출하고 있는 포트를 보여줍니다.
Docker Compose는 컨테이너 내부에서 터미널 명령을 실행하거나 명령줄에 액세스하는 데 사용할 수 있는 exec라는 명령을 제공합니다. 먼저 Laravel 앱을 실행 중인 컨테이너인 app 컨테이너 내부에서 몇 가지 명령을 실행하고자 합니다.
Docker는 컨테이너의 명령줄에 액세스할 수 있는 명령을 제공합니다. 구문은 다음과 같습니다: docker-compose exec container_name bash. app 컨테이너의 명령줄에 액세스하려면 다음 명령을 입력하십시오:
|
1 |
docker-compose exec app bash |
컨테이너의 명령줄에 접속하면 몇 가지 Laravel Artisan 설정 명령을 실행할 수 있습니다. 다음 명령을 입력하여 laravel 키를 생성하고 .env 파일에 저장하십시오:
|
1 |
php artisan key:generate |
환경 키가 설정되면 다음 명령을 실행하여 설정 구성을 캐시할 수 있습니다:
|
1 |
php artisan config:cache |
설정은 컨테이너 내부의 /var/www/html/bootstrap/cache/config.php 파일에 저장됩니다. Ctrl + D를 눌러 컨테이너 터미널을 종료할 수 있습니다.
Laravel 앱이 배포되어 실행 중인지 확인하려면 브라우저에서 서버의 퍼블릭 IP(http://your_server_public_ip)에 접속하십시오. 새 Laravel 설치에 대한 환영 페이지가 표시되어야 합니다:

10단계: MySQL 사용자 구성
이 단계에서는 docker-compose 파일에 지정한 MySQL 데이터베이스 laravel_web에 대한 데이터베이스 사용자를 생성합니다. 컨테이너 빌드 명령을 실행했던 9단계, MySQL이 설치되었지만, 데이터베이스에 무제한 권한을 가진 기본 root 관리자 계정만 생성되었습니다. root 사용자를 사용하지 않기 위해, 애플리케이션에 사용할 전용 사용자인 laraveldocker를 생성하겠습니다. 이 사용자는 다음의 환경 변수에서 지정한 사용자입니다: 8단계. 다음 명령어를 입력하여 터미널 내부의 명령줄에 액세스합니다:
|
1 |
docker-compose exec db bash |
컨테이너 내부에 들어가면, 다음 명령어를 입력하여 MySQL에 로그인합니다:
|
1 |
mysql -u root -p |
비밀번호 입력 프롬프트에서, 다음의 docker-compose 파일 내 db 서비스에 설정한 비밀번호를 입력합니다: 2단계.
MySQL 프롬프트에 로그인한 후, 다음 SQL 명령어를 입력하여 docker-compose 파일에 지정한 데이터베이스가 보이는지 확인합니다:
|
1 |
show databases; |
laravel_web 데이터베이스 또는 설정 시 지정한 이름이 표시되어야 합니다:

다음으로, laravel_web 데이터베이스의 사용자 및 비밀번호를 생성합니다. 이는 다음의 .env 파일에 지정한 정보와 동일해야 합니다: 8단계. 다음 명령어를 입력하여 사용자와 비밀번호를 생성하고, 이 사용자에게 모든 권한을 부여합니다:
|
1 |
GRANT ALL ON laravel_web.* TO 'laraveldocker'@'%' IDENTIFIED BY 'your_strong_laravel_docker_password'; |
변경 사항을 즉시 적용하려면, 다음 명령어를 입력하여 권한을 플러시(flush)합니다:
|
1 |
FLUSH PRIVILEGES; |
이것으로 MySQL 사용자 설정이 완료되었습니다. exit를 입력하고 엔터를 눌러 MySQL 프롬프트를 종료합니다. 마지막으로 Ctrl + D를 눌러 db 컨테이너를 종료합니다.
11단계: Laravel 애플리케이션 코드와 MySQL 데이터베이스 간의 통신 테스트
이 단계까지는 모든 것이 잘 작동했습니다. 하지만 app 컨테이너의 Laravel 코드가 db 컨테이너의 MySQL 데이터베이스와 통신할 수 있는지 확인하고자 합니다. 먼저, 다음 명령어를 입력하여 app 컨테이너 터미널에 접속합니다:
|
1 |
docker-compose exec app bash |
다음으로 laravel migration 명령어를 실행하여 테이블을 생성합니다:
|
1 |
php artisan migrate |
Laravel이 기본 테이블을 생성할 때 터미널에서 마이그레이션 프로세스를 확인할 수 있습니다:

다음으로, Laravel에서 데이터베이스에 액세스할 수 있는지 테스트해 보겠습니다. Laravel에는 기본적으로 Tinker가 포함되어 있어 데이터베이스 액세스, 작업 실행, eloquent ORM 등을 포함하여 명령줄에서 전체 애플리케이션과 상호 작용할 수 있습니다. Tinker를 사용하여 migrations 테이블의 데이터를 볼 수 있습니다. 다음 명령어를 입력하여 Tinker에 접속합니다:
|
1 |
php artisan tinker |
Tinker 프롬프트에 진입하면, 다음을 입력하여 migrate 명령어로 생성된 테이블 목록을 확인할 수 있습니다:
|
1 |
\DB::select('show tables'); |
아래 스크린샷은 현재 laravel_web 데이터베이스에 있는 테이블인 출력 결과를 보여줍니다:

테이블 이름을 지정하여 테이블의 데이터를 조회할 수 있습니다. 예를 들어, 다음 명령어를 입력하여 migrations 테이블의 데이터를 조회할 수 있습니다:
|
1 |
\DB::table('migrations')->get(); |
명령어는 다음과 같이 출력됩니다:

위의 출력 결과에서 볼 수 있듯이, Laravel 애플리케이션이 잘 구성되어 데이터베이스와 통신할 수 있습니다. 모델 생성, 작업 실행 등 더 많은 명령어를 실험해 볼 수 있습니다. Ctrl + D를 누르면 Tinker 프롬프트를 종료할 수 있습니다.
결론
이 튜토리얼에서는 Docker 컨테이너 내에 LEMP 스택 Laravel 애플리케이션을 배포했습니다. 웹 인터페이스에 액세스하고 Laravel Tinker를 통해 데이터베이스에 연결하여 애플리케이션을 테스트했습니다. Docker Compose의 강력함을 경험할 수 있었습니다. 이를 통해 하나의 파일에 정의된 Docker 컨테이너 그룹을 생성하고, 단 하나의 명령어로 실행할 수 있습니다.
컨테이너에 대해 더 자세히 알아보고 싶다면, 저희의 Docker 리소스(이미지, 컨테이너, 볼륨)를 정리하는 방법을 알려주는 튜토리얼 및 저희의 Kubernetes 도구에 대한 자세한 개요.
저희 블로그를 방문하여 다음에 대해 더 알아보실 수 있습니다: Docker와 지속적 통합 및 지속적 배포.
즐거운 컴퓨팅 되세요!
댓글
아직 댓글이 없습니다. 첫 번째로 작성해 보세요.