본문 바로가기

교육/42서울

42 inception 과제 기초 가이드 - 도커 컴포즈로 실제 서비스를 올려보자

728x90

42 서울 inception 과제는 docker-compose를 사용하여 여러 도커 파일들을 컨테이너로 올려야한다. 

ft_server라는 과제가 있었지만 지금은 사라졌다. Dockerfile 하나로 컨테이너를 올려서 서비스를 관리하는 방법이 궁금하다면, ft_server를 검색해보면 카뎃들이 작성한 좋은 글들을 많이 볼 수 있다.

 

이 글에서는 간단한 도커 컴포즈 파일(docker-compose.yaml)을 작성하여, 간단하게 Wodrpess 서비스를 올려보는 과정을 실습해본다. 

 

inception 실습을 해보기 전에 quickstart: docker-compose wordpress 예제를 해보는 것을 추천한다.

 

 

1.  과제에서 목표로 하는 시스템 구성도

총 3개의 도커이미지를 사용하여 컨테이너를 띄어야 한다. 

 

 

2.  도커 컴포즈 파일 작성하고 실행하기

실습을 진행할 컨테이너 환경은 대략 위와 같은 시스템 구성도를 가지고 있다. 

wordpress 서버 구동에 필요한 최소한의 환경들로만 구성을 하였다.

 

 

2.1. 실습에서 사용할 docker-compose.yaml 파일

$ cat docker-compose.yaml

version: '3'

volumes:
    data: {}
services:
    mariadb:
        image: debian:buster
        restart: always
        expose:
            - "3306"
        networks:
            - intra
        tty: true
    nginx:
        image: debian:buster
        restart: always
        ports:
            - "443:443"
        volumes:
            - data:/var/www/html
        networks:
            - intra
        tty: true
    wordpress:
        image: debian:buster
        restart: always
        volumes:
            - data:/var/www/html
        expose: 
            - "9000"
        networks:
            - intra
        tty: true
networks:
    intra:
        driver: bridge

 

debain:buster 3개의 도커 이미지를 사용하여 간단한 docker-compose.yaml 파일을 작성하였다. docker-compose.yaml 파일 링크 

 

docker-compose version 3이다. 버전마다 작성해야하는 형식이 다르므로, 주의해야 한다. Docker file 공식문서 버전

volumes에 정의한 볼륨 이름은 data이다. 해당 볼륨은 Docker에서 관리한다.

services는 총 3개를 컨테이너를 띄우도록 작성하였다. mariadb, nginx, wordpress. 

networks의 이름은 intra이고, bridge 방식으로 생성을 하였다. (not host)

 

 

$ docker-compose up --build -d

Docker Compose is now in the Docker CLI, try `docker compose up`

Creating inception_nginx_1     ... done
Creating inception_mariadb_1   ... done
Creating inception_wordpress_1 ... done
Attaching to inception_mariadb_1, inception_wordpress_1, inception_nginx_1

docker-compose up 명령어로 컨테이너들을 생성하고 시작할 수 있는데 --build 옵션을 주어 services들을 빌드할 수 있고, -d 옵션으로 데몬 환경으로 동작하도록 하였다.

 

 

$ docker-compose ps

        Name            Command   State                  Ports
------------------------------------------------------------------------------
inception_mariadb_1     bash      Up      3306/tcp
inception_nginx_1       bash      Up      0.0.0.0:443->443/tcp,:::443->443/tcp
inception_wordpress_1   bash      Up      9000/tcp

docker-compose ps 커맨드로 위와 같이 보인다면 제대로 컨테이너들이 시작되었다고 볼 수 있다. 

 

만약 도커 컨테이너를 멈추고 제거까지 하고 싶다면 docker-compose down을 해주면 된다. 그 외에 명령어는 docker-compose --help를 하면 볼 수 있다. 

 

 

3.  컨테이너에 접속하는 여러 방법

실습을 위해 maridb, nginx, wordpress 컨테이너에 접근을 해야 한다. 

실행 중인 컨테이너를 bash 쉘로 통해 접근할 수 있으며, 내가 필요로 하는 패키지를 직접 설치하고, 파일을 작성하고, 테스트할 수 있다. 

 

3.1. docker 명령어로 접속하기

$ docker ps         

CONTAINER ID   IMAGE           COMMAND   CREATED          STATUS          PORTS                                   NAMES
0ba436eccbc5   debian:buster   "bash"    21 minutes ago   Up 21 minutes   3306/tcp                                inception_mariadb_1
d4e4b424c3cf   debian:buster   "bash"    21 minutes ago   Up 21 minutes   0.0.0.0:443->443/tcp, :::443->443/tcp   inception_nginx_1
487d0433b6c9   debian:buster   "bash"    21 minutes ago   Up 21 minutes   9000/tcp                                inception_wordpress_1

docker ps로 컨테이너 리스트들을 볼 수 있다.

 

$ docker exec -it 0ba436eccbc5 /bin/bash
root@0ba436eccbc5:/#

docker exec 명령어를 사용하여, 컨테이너 ID가 0ba436ecbc5 인 컨테이너의 bash쉘을 실행시킴으로써 접근할 수 있다.

 

 

 

3.2 docker-compose 명령어로 접속하기

$ docker-compose exec mariadb /bin/bash
root@0ba436eccbc5:/#

 

docker-compose exec 명령어를 사용하여, 서비스명이 mariadb인 컨테이너의 bash쉘을 실행시킴으로써 접근할 수 있다.

docker-compose.yaml 파일이 존재하는 곳에서만 위 명령어로 실행할 수 있다.

 

services:
    mariadb:
        image: debian:buster

뒤에 오는 mariadb는 docker-compose.yaml에서 작성한 services 명이다. 

 

예를 들어 docker-compose exec nginx,  docker-compose exec wordpress로 각 컨테이너들에게 원하는 명령어를 전달할 수 있다.

 

 

4.  MariaDB 설치하기

mariadb 컨테이너는 3306 포트로 DB서버를 제공해야 한다. 

4.1. mariadb 서비스 컨테이너에 접근하기

$ docker-compose exec mariadb /bin/bash
root@0ba436eccbc5:/#

DataBase 설치 및 서비스하기 위해 mariadb 컨테이너에 접근을 하였다.

 

4.2. mariadb-server 설치 및 시작

root@0ba436eccbc5:# apt-get update -y && \
apt-get upgrade -y && \
apt-get -y install mariadb-server

패키지 정보를 업데이트하고, 설치된 패키지를 업그레이드 해준 뒤 mariadb-server를 설치한다.

 

 

root@0ba436eccbc5:# apt-get install -y vim

root@0ba436eccbc5:# vim /etc/mysql/mariadb.conf.d/50-server.cnf

# bind-addres  = 127.0.0.1

mariadb 서버의 bind-address 주소를 주석 처리해준다. 이를 해주질 않을 경우 외부 ip에서 접근할 수 없게 된다.

mysqld를 사용할 경우  --bind-address = 0.0.0.0을 옵션을 추가해주면 된다.

 

root@0ba436eccbc5:# service mysql start

[ ok ] Starting MariaDB database server: mysqld.

mysql 서비스를 시작한다. 

 

 

4.3. wordpress에서 사용할 유저와 DB 생성하기

root@0ba436eccbc5:# mysql 

MariaDB [(none)]> CREATE DATABASE wordpress_db;

mysql로 들어간 뒤, wordpress_db를 만들어준다. 

 

CREATE USER 'epicarts'@'%' IDENTIFIED BY 'password';
GRANT ALL ON wordpress_db.* TO 'epicarts'@'%';
FLUSH PRIVILEGES;

유저의 아이디와 패스워드를 만든 뒤, wodrpess_db의 모든 테이블을 어디에서든 접속할 수 있게 설정한다. 

유저 이름은 epicarts, 패스워드는 password라고 생성하였다.

 

 

4.4. MariaDB 서버 접속이 잘 되는지 확인하기

MariaDB [(none)]> exit
Bye

root@0ba436eccbc5:# hostname -i
172.25.0.3

 

설정이 잘되었는지 확인하기 위해서 먼저 mysql 서버에서 빠져나온다. 

mariadb 컨테이너의 IP주소를 확인해보자. 172.25.0.3이다. 

실습 환경에 따라 다르므로 꼭 확인해야 한다.

 

 

root@0ba436eccbc5:# exit

mariadb 컨테이너를 빠져나온다.

 

$ docker-compose exec wordpress /bin/bash

root@487d0433b6c9:/# apt-get update -y && \
apt-get upgrade -y && \
apt-get -y install mariadb-client

이제 wodrpess 컨테이너로 접속한 후 mysql-client를 설치한다.

 

root@8b41a90ef8e8:/# mysql -u epicarts -ppassword -h 172.25.0.3

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 40
Server version: 10.3.27-MariaDB-0+deb10u1 Debian 10

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 

host부분에 mariadb 컨테이너 주소를 적고 mysql서버에 접근할 수 있다. 

위와 같이 보인다면 제대로 접속이 된 것이다. 

 

 

 

5.  wordpress 환경 설정하기

wordpress 컨테이너는 9000 포트로 php-fpm 서버를 제공해야 한다. 

5.1. wordpress 서비스 컨테이너에 접근하기

$ docker-compose exec wordpress /bin/bash

이제 wordpress 환경을 설정해보자. wodrpress 컨테이너로 접속한다.

 

5.2. wordpress  컨테이너에 필요한 패키지 설치하기

root@8b41a90ef8e8:/# apt-get update -y && \
apt-get upgrade -y && \
apt-get -y install \
php7.3 \
php-fpm \
php-cli \
wget \
curl \
php-mysql \
php-mbstring \
php-xml \
sendmail \
vim

php-fpm구동과 wodrpess를 다운로드하는데 필요한 패키지들을 설치해준다.

 

5.3. wordpress 다운로드하기

wget https://wordpress.org/latest.tar.gz && \
tar -xvf latest.tar.gz && \
mv /wordpress/* /var/www/html/ && \
chown -R www-data:www-data /var/www/html && \ 
rm -r /wordpress latest.tar.gz

wodrpess latest 버전을 다운로드한 뒤 압축을 풀고 /var/www/html/ 에 이동시킨다.

해당 폴더는 docker-compose.yaml 파일에서 정의한 data라는 볼륨에 마운트 되어 있다.

 

 

root@8b41a90ef8e8:/# ls -l /var/www/html/
total 212
-rw-r--r--  1 www-data www-data   612 Jun 17 12:05 index.nginx-debian.html
-rw-r--r--  1 www-data www-data   405 Feb  6  2020 index.php
-rw-r--r--  1 www-data www-data 19915 Jan  1 00:19 license.txt
-rw-r--r--  1 www-data www-data  7345 Dec 29 20:14 readme.html
-rw-r--r--  1 www-data www-data  7165 Jan 21 01:37 wp-activate.php
drwxr-xr-x  9 www-data www-data  4096 May 12 23:49 wp-admin
-rw-r--r--  1 www-data www-data   351 Feb  6  2020 wp-blog-header.php
-rw-r--r--  1 www-data www-data  2328 Feb 17 13:08 wp-comments-post.php
-rw-r--r--  1 www-data www-data  2913 Feb  6  2020 wp-config-sample.php
drwxr-xr-x  4 www-data www-data  4096 May 12 23:49 wp-content
-rw-r--r--  1 www-data www-data  3939 Jul 30  2020 wp-cron.php
drwxr-xr-x 25 www-data www-data 12288 May 12 23:49 wp-includes
-rw-r--r--  1 www-data www-data  2496 Feb  6  2020 wp-links-opml.php
-rw-r--r--  1 www-data www-data  3313 Jan 10 19:28 wp-load.php
-rw-r--r--  1 www-data www-data 44994 Apr  4 18:34 wp-login.php
-rw-r--r--  1 www-data www-data  8509 Apr 14  2020 wp-mail.php
-rw-r--r--  1 www-data www-data 21125 Feb  2 00:10 wp-settings.php
-rw-r--r--  1 www-data www-data 31328 Jan 27 21:03 wp-signup.php
-rw-r--r--  1 www-data www-data  4747 Oct  8  2020 wp-trackback.php
-rw-r--r--  1 www-data www-data  3236 Jun  8  2020 xmlrpc.php

위와 같이 되었다면, 제대로 된 것이다.

 

5.4. wp-config.php 파일 수정

root@8b41a90ef8e8:/# mv /var/www/html/wp-config-sample.php /var/www/html/wp-config.php

wp-config-sample.php 파일을 wp-config.php으로 변경해준다.

 

 

root@8b41a90ef8e8:/# vim /var/www/html/wp-config.php

wp-config 파일을 수정해야 한다. 

 

mariadb 컨테이너에서 설정하였던 유저 정보와 패스워드, host주소를 적어준다. 

 

 

5.5. php fpm 설정 파일 수정

root@8b41a90ef8e8:/# vim /etc/php/7.3/fpm/pool.d/www.conf

php-fpm을 실행시키기 전에 있어 외부에서 php fpm 서비스에 접속할 수 있게 설정을 해주어야 한다. 

php-FPM(FastCGI Process Manager)은 요청마다 이미 생성한 프로세스를 재활용함으로써, 빠르게 동작하는 CGI(Common Gateway Interface)이다.

 

www.conf 파일의 listen을 위와 같이 0.0.0.0:9000으로 수정한 뒤 저장을 한다. 

이제 외부에서도 php-fpm을 호출할 수 있을 것이다.

 

5.6. php fpm 서비스 시작

service php7.3-fpm start

php7.3-fpm을 시작한다.

 

 

root@8b41a90ef8e8:/# hostname -i

172.25.0.2

마지막으로 nginx 컨테이너 설정으로 넘어가기 전에 ip주소를 메모해둔다. nginx에서 php-fpm서버에 접근을 해야 하므로 필요하다.

wordpress 컨테이너의 주소는172.25.0.2이다.

 

 

 

6.  Nginx 환경 설정하기

nginx 컨테이너는 443 포트로 웹 서버를 제공 해야한다. 

6.1. nginx 서비스 컨테이너에 접근하기

$ docker-compose exec nginx /bin/bash

이제 nginx 환경을 설정해보자. nginx 컨테이너로 접속한다.

 

 

6.2. nginx 필요한 패키지 설치하기

root@3652dd165a94:/# apt-get update -y && apt-get upgrade -y && \
apt-get -y install nginx openssl vim

openssl과 nginx를 설치한다.

openssl 은 443포트로 https 통신을 하기 위해 self-signed SSL 인증서를 생성하기 위해 설치하였다.

 

 

6.3. self-signed ssl 인증서 만들기

root@3652dd165a94:/# openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/server_pkey.pem -out /etc/ssl/certs/server.crt

Generating a RSA private key
..+++++
..................................................................................................+++++
writing new private key to '/etc/ssl/certs/server_pkey.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

x.509 인증서를 만든다. 

개인키는 /etc/ssl/private/server_pkey.pem 에 저장을 하였고, 공개키로 서명한 CRT 인증서는 /etc/ssl/certs/server.crt 에 저장을 하였다.

위 단계를 더 세분화하여 개인키를 사용하여 CSR(Certificate Signing Request)을 만들고, 사인하는 과정을 나누어 작업할 수 있으나, 여기에서는 생략하였다.

 

만약 인증서 구조에 대해 궁금한 사람들은 x.509 인증서(certificate) 서명 값(signature) 검증해보기를 보면 좋을듯하다.

 

6.4. default 파일 수정하기 

root@3652dd165a94:/# vim /etc/nginx/sites-available/default

nginx에서 php 확장자를 호출했을 경우 

 

server {
	listen 443 ssl;
	ssl_protocols  TLSv1.2 TLSv1.3;
    
	ssl_certificate /etc/ssl/certs/server.crt;
	ssl_certificate_key /etc/ssl/private/server_pkey.pem;

	root /var/www/html;

	index index.php index.html index.htm;

	server_name _;

	location / {
		try_files $uri $uri/ =404;
	}

	location ~ \.php$ {
		include snippets/fastcgi-php.conf;
        
		# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
		fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
		fastcgi_pass 172.25.0.2:9000;
	}
}

중요한 부분만 간단하게 살펴보자.

nginx 서버는 443으로 요청을 듣고, ssl_protocol로 TLSv1.2와 TLSv1.3을 사용한다.

 

fastcgi_param 에는 fastcgi에 전달하고 싶은 파라미터를 적으면 된다.

SCRIPT_FILENAME 파라미터는 php-fpm가 어떤 파일을 처리해야 하는지 알려준다. 즉, 처리할 파일의 위치를 전달한다. 

 

처리할 파일의 위치는 docker-compose.yaml을 보면 data라는 이름의 volume으로 /var/ww/html 폴더를 공유하고 있다. nginx와 wodpress 컨테이너 둘 다 같은 wordpress 폴더를  공유하고 있다. 

 

만약, 우리가 wodpress 컨테이너에서 wordpress 압축 해제한 경로를 /var/www/html/wodrpess/ 에 풀었다고 가정을 해보자.

"fastcgi_param SCRIPT_FILENAME /var/www/html/wodpress/$fastcgi_script_name;"

라고 적어야 할 것이다. 

 

6.5. nginx 서비스 시작하기

root@3652dd165a94:/# service nginx start
[ ok ] Starting nginx: nginx.

nginx 서버를 시작하고 이제 웹브라우저로 접속을 해보자.

 

 

https://127.0.0.1로 접근한다면 위와 같은 페이지로 접근할 것이다. http로 접근은 불가능하기 때문에 꼭 https로 접근해야 한다.

크롬 브라우저로 접근이 안된다면, 빈 곳을 클릭하고 thisisunsafe라고 입력을 하자. 

방금 말이 이해가 안 된다면 구글에 크롬 this is unsafe라고 검색을 하면 여러 방법들이 나올 것이다. self-signed 인증서라 그렇다.

 

 

https://127.0.0.1/index.php로 접근하면 설치 페이지로 리다이렉션 될 것이다.

 

 

이후 과제를 진행하면서 참고하면 좋을 내용

 

Read about PID 1 and the best practices for writing Dockerfiles.

특히 과제에 PID1과 좋은 도커 파일을 작성하는 방식에 대해 적어놓았는데, Google 컨테이너 빌드에 대한 권장사항 글을 읽어보면 좋다. 

docker는 컨테이너 내부에 PID 1이 있는 프로세스에만 신호를 보낼 수 있다.

 

ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 80

STOPSIGNAL SIGQUIT

CMD ["nginx", "-g", "daemon off;"]

Dockerfile의 Entrypoint 작성하는 좋은 방법으로 nginx docker github를 참고하였다.

링크: https://github.com/nginxinc/docker-nginx/tree/master/stable/debian

 

또한 우리가 docker pull nginx:latest 하여 다운로드하는 이미지들은 docker hub 저장되어 있으며 nginx 이미지처럼 github로 공개되어 있는 경우가 많았다. 이를 참고하면 좋은 도커 파일을 작성할 수 있지 않을까 생각한다. 전부 이해하지 못해서 이해한 부분만 가져다 썼지만..

예) docker hub nginxdocker hub mariadb

 

 

 

MariaDB 팁

mysql_install_db 명령어를 사용하면 mysql 데이터 디렉터리를 초기화시킬 수 있다. 기본으로 사용되는 디렉터리(/var/lib/mysql)를 사용하지 않고자 할 때 사용하면 유용하다.

 

mysqld_safe를 사용하여 mysql서버를 실행시킬 수 있는 방법이 있다. 

링크: MYSQL튜닝 기술 mysqld_safe

 

mysqladmin 명령어로 mysql을 사용하여 데이터베이스 생성, 루트 패스워드 설정 등 다양한 작업을 쉘로 할 수 있다.

 

$ mysql -u root -p"ROOT_PASSWORD"<<-EOSQL
	CREATE DATABASE MYSQL_DATABASE;
EOSQL

EOSQL를 사용하여 Shell을 통해 SQL 쿼리를 전달할 수 있다.

 

 

php-fpm 팁

설정을 어떻게 해야 할지 고생하고 있을 때, 생활 코딩 php-fpm, mysql 연동 강의 가 도움이 많이 되었다. 

 

 

wp-config.php 에 설정한 php 환경변수가 제대로 적용되지 않을 때, /etc/php/7.3/fpm/pool.d/www.conf 파일을 살펴보자.

clear_env = no 주석을 해제해야 한다. 

이거 때문에 고생을 참 많이 했다.

 

 

Wordpress  팁

https://wp-cli.org/

wp-cli라는 wordpress CLI 툴이 있다. 이를 사용하면 웹 브라우저가 아닌 쉘로도 워드프레스를 설치할 수 있다. 워드프레스 자동 설치할때 도움이 된다.

 

 

Docker compose 팁

 

각 컨테이너 서비스들을 ip주소로 직접 접근하지 않고, alias로 서비스마다 별칭을 사용하여 접근할 수 있다. docker 공식문서의 네트워크 부분을 살펴보자.

링크: https://docs.docker.com/compose/compose-file/compose-file-v3/#networks

 

 

docker-compose depends_on으로 종속성을 표현하고 서비스들을 실행시킬 수 있다. 하지만 내부적으로 서비스가 완전히 실행될 때까지 보장하지 않는다.  

링크: https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on

 

728x90