Docker NGINX 구축 및 구동 연습

ft_server 선행지식

Docker 입문

ft_server 서비스 목록

Install Docker Engine on Debian

docker stop $(docker ps -aq)
docker system prune -a

도커 컨테이너 모든 이미지 삭제 명령어

=> docker stop $(docker ps -aq -f "name=ft_server")

docker rm $(docker ps -aq -f "name=ft_server")

docker rmi $(docker images -aq ft_server)

docker pull debian:buster

도커 명령어를 통해 Debian Buster 이미지를 생성한다.

docker run -it --name con_debian -p 80:80 -p 443:443 debian:buster

도커 명령어를 통해 데비안 버스터 환경 실행 및 접속

위 명령어를 실행하게 되면 아래 스크린샷과 같이 데비안 버스터 환경에서의 bash에 접속하게 된다.

docker run 명령어에 대한 옵션은 다음과 같다. 

-i 옵션 : interactive(입출력)

-t 옵션 : tty(터미널)를 활성화하는 옵션으로써 일반적으로 터미널 사용하는 것처럼 컨테이너 환경을 만들어주는 옵션

--name [컨테이너 이름] 옵션 : 컨테이너 이름을 지정.

-p 호스트 포트 번호 : 컨테이너 포트 번호 옵션은 컨테이너의 포트를 개방한 뒤 호스트 포트와 연결한다. 

:buster : 자동으로 최신 버전을 불러온다.

docker를 종료하고 싶을 경우 docker bash 쉘에서 exit 명령어를 실행

docker start [컨테이너 이름 또는 아이디]
docker restart [컨테이너 이름 또는 아이디]

docker 컨테이너를 재시작, 재실행을 하고 싶을 경우 위 명령어를 실행    

docker attach [컨테이너 이름 또는 아이디]

가동된 docker 컨테이너를 접속하고 싶을 경우 위 명령어를 수행

apt-get update && apt-get upgrade

update는 설치 되어있는 패키지들의 새로운 버젼이 있는지 확인할 때 해당 명령어를 사용한다.

update를 통해서 확인한 패키지들의 최신 버전으로 업그레이드 해주는 명령어이다.

apt-get -y install nginx curl

service nginx start

service nginx status

apt-get -y install openssl

openssl req -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=bahn/CN=localhost" -keyout localhost.dev.key -out localhost.dev.crt

위 명령들을 실행해보면 아래 스크린샷과 같이 개인키 localhost.dev.key와 인증서 localhost.dev.crt가 생성된다.

mv localhost.dev.crt etc/ssl/certs/

인증서를 etc/ssl/certs 경로로 이동시켜준다.

mv localhost.dev.key etc/ssl/private/

개인키를 etc/ssl/private 경로로 이동시켜준다.

chmod 600 etc/ssl/certs/localhost.dev.crt etc/ssl/private/localhost.dev.key

인증서와 개인키의 권한을 600 으로 설정해준다.

즉, 인증서와 개인키에 대해서 user 권한자만 읽기, 쓰기 권한을 가질 수 있다.

apt-get install vim

vim etc/nginx/sites-available/default

default 파일에 https 연결을 위한 설정을 작성한다.

원래는 서버 블록이 하나이며 80번 포트만 수신대기 상태인데, https 연결을 위해 443 포트를 수신대기하고 있는 서버 블록을 추가로 작성해야 한다.

nginx configuration 파일 구조

nginx는 여러 개의 모듈들로 구성되어 있는데, 
그것들은 conf 파일 안의 디렉티브(directives)에 의해 제어된다. 
디렉티브들은 심플 디렉티브(simple directives)와 블록 디렉티브(block directives)로 나뉜다. 
심플 디렉티브의 이름과 파라미터는 스페이스(spaces)에 의해 구분되고 세미콜론(;)으로 끝난다. 
블록 디렉티브는 심플 디렉티브와 기본적으로는 동일한 구조를 가지는데, 
하지만 세미콜론 대신에 그것은 중괄호(braces)로 둘러싸인 추가적인 명령들의 집합이 뒤에 붙는다. 
그리고 만약 블록 디렉티브가 중괄호 안에 다른 디렉티브를 가질 수 있으면 
그것은 컨텍스트(context)라고 불린다(e.g. events, http, server 그리고 location 등).

conf 파일 안에서 다른 컨텍스트 밖에 있는 디렉티브들은 
모두 메인 컨텍스트(main context) 안에 있는 것으로 본다.
events와 http 디렉티브는 메인 컨텍스트 안에 있는 것이고, 
server 디렉티브는 http 컨텍스트 안에, 
그리고 location 디렉티브는 server 컨텍스트 안에 있는 것이다.

그리고 # 기호 이후에 오는 모든 줄은 주석으로 간주된다.
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##

# Default server configuration
#
server {
        listen 80;
        listen [::]:80;

        return 301 https://$host$request_uri;
}

server {
        listen 443;
        listen [::]:443;

        # SSL configuration
        #
        # listen 443 ssl default_server;
        # listen [::]:443 ssl default_server;
        #
        # Note: You should disable gzip for SSL traffic.
        # See: https://bugs.debian.org/773332
        #
        # Read up on ssl_ciphers to ensure a secure configuration.
        # See: https://bugs.debian.org/765782
        #
        # Self signed certs generated by the ssl-cert package
        # Don't use them in a production server!
        #
        # include snippets/snakeoil.conf;

        ssl on;
        ssl_certificate /etc/ssl/certs/localhost.dev.crt;
        ssl_certificate_key /etc/ssl/private/localhost.dev.key;

        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.php; #index.nginx-debian.html;

        server_name ft_server;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                autoindex on;
                try_files $uri $uri/ =404;
        }

        # pass PHP scripts to FastCGI server
        #
        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
        #
        #       # With php-fpm (or other unix sockets):
        #       fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
                fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
        #       # With php-cgi (or other tcp sockets):
        #       fastcgi_pass 127.0.0.1:9000;
        }

        # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #       deny all;
        #}
}


# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
#       listen 80;
#       listen [::]:80;
#
#       server_name example.com;
#
#       root /var/www/example.com;
#       index index.html;
#
#       location / {
#               try_files $uri $uri/ =404;
#       }
#}

service nginx reload

apt-get install php-fpm

위 명령어를 통해 PHP FastCGI Process Manager 패키지를 설치해본다.

일반 GCI 보다 빠른 처리가 가능한 FastGCI이다.

php-fpm 을 통해 nginx와 php를 연동시켜 우리의 웹 서버가 정적 콘텐츠 뿐만 아니라 동적 콘텐츠를 다룰 수 있도록 만든다.

그리고나서 default 파일에 php에 대한 설정을 추가해준다.

...
index index.html index.htm index.nginx-debian.html index.php;

location ~ \.php$ {
		include snippets/fastcgi-php.conf;
		fastcgi_pass unix:/var/run/php/php7.3-fpm.sock;
}
...

루트 디렉터리인 /var/www/html 에 존재하는 index.nginx-debian.html 을 주석처리해보면,

읽을 파일이 없다고 생각하고 아래처럼 전체 파일 목록을 반환하는 것을 확인할 수 있다.

데비안 버스터에서는 mariaDB만을 지원한다.

mariaDB는 mysql을 기반으로 만들어졌기때문에

mysql 명령어와 완전히 호환된다.

php-mysql은 php에서 mysql에 접근할 수 있게 해주는 모듈이다.

php-mbstring은 2바이트 확장 문자를 읽을 수 있도록 해주는 모듈이다.

apt-get -y install mariadb-server php-mysql php-mbstring

apt-get install -y wget

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/wordpress

cp -rp var/www/html/wordpress/wp-config-sample.php var/www/html/wordpress/wp-config.php

vim var/www/html/wordpress/wp-config.php

service mysql start

mysql #

MariaDB(MySQL)> CREATE DATABASE wordpress;

MariaDB(MySQL)> SHOW DATABASES;

MariaDB(MySQL)> CREATE USER 'bahn'@'localhost' IDENTIFIED BY '1234';

MariaDB(MySQL)> GRANT ALL PRIVILEGES ON wordpress.* TO 'bahn'@'localhost' WITH GRANT OPTION;

MariaDB(MySQL)> USE wordpress;

MariaDB(MySQL)> SHOW TABLES;

service php7.3-fpm restart

mysql 쿼리 실행까지 모두 잘 마치고

php-fpm 을 실행시켜려하는데 계속 [FAIL] 메시지가 뜨면서 실패한다.

1시간 가량 구글링 통해 해결 방법을 찾았다.

vim etc/php/7.3/fpm/pool.d/www.conf

www.conf 설정 파일로 들어가 listen 변수(?)의 경로를 수정해주었다.

listen = /run/php/php7.3-fpm.sock   ->    listen = /var/run/php/php7.3-fpm.sock

하나의 고비를 넘긴 것 같아 심신이 안정된 것 같다.

이제 phpMyAdmin을 설치해보자.

wget https://files.phpmyadmin.net/phpMyAdmin/5.0.2/phpMyAdmin-5.0.2-all-languages.tar.gz

tar -xvf phpMyAdmin-5.0.2-all-languages.tar.gz

mv phpMyAdmin-5.0.2-all-languages phpmyadmin

mv phpmyadmin /var/www/html/

cp -rp var/www/html/phpmyadmin/config.sample.inc.php var/www/html/phpmyadmin/config.inc.php

blowfish 암호 생성

위 링크로 접속하여 키를 복사한 후

config.inc.php 파일의 $cfg['blowfish_secret'] 변수에 대입한다.

vim var/www/html/phpmyadmin/config.inc.php

service nginx reload

service mysql start

mysql < var/www/html/phpmyadmin/sql/create_tables.sql

phpmyadmin/sql 폴더의 create_table.sql 파일을 mysql로 리다이렉션 시켜준다.

https://localhost/phpmyadmin/ 링크로 들어가니

정상적으로 phpMyAdmin 로그인 페이지가 출력되고 로그인 과정 또한 잘 동작한다.


ft_server - 총 정리 도커 설치부터 워드프레스 구축까지

ft_server - 서비스 목록

NGINX 소개

CURL 이란?

ft_server - Dockerfile 명령문 문법

  • FROM

    FROM은 어떤 이미지를 기반으로 이미지를 생성할 것인지 정의한다.
    FROM <이미지>:<태그> 형식을 가진다.
    태그는 해당 이미지의 별칭으로, 입력하지 않으면 latest(최신버전)가 디폴트로 붙는다.
    당연하게도 <이미지>는 생략할 수 없다.
    이미지를 생성할 때 과거에 생성한 적 있는 기반 이미지라면
    이미 로컬에 데이터가 있을 것이므로 그대로 불러와서 활용하고,
    없으면 Docker Hub에서 받아온다.
    FROM을 여러개 사용하여 Dockerfile 하나에 여러개의 기반이미지를 가져올 수 있다.
    FROM을 두 개 쓰면 두 개의 이미지가 생성되는 것이다.

    ft_server 과제는 debian:buster 이미지를 요구하므로

    "FROM debian:buster" 형식으로 작성한다.

  • MAINTAINER

    MAINTAINER는 이미지를 생성한 사람의 정보를 입력한다. 자유형식 입력이 가능하다.

    MAINTAINER bahn bbu0704@gmail.com 형식으로 작성해보았다.

  • RUN

    RUN은 FROM에서 설정한 이미지 위에서 명령어를 실행시킨다.
    RUN에 의해 실행된 쉘스크립트 명령의 결과가 새로운 이미지로 생성되고
    실행 내역은 이미지 히스토리에 기록된다.

    쉘 명령이 실행되는 원리는 FROM에서 가져온 이미지에 담겨잇는
    /bin/sh 실행파일을 이용하는 것이다.

    실행 결과는 캐시되고, 다음 빌드할 때 재사용된다. 캐시를 재활용하고 싶지 않으면 docker build 명령에서 --no-cache 옵션을 사용한다.

    RUN 명령은 /bin/sh 상에서 실행되지 않고 바로 실행시키는 방법도 있다.

    RUN ["쉘명령어","매개변수1","매개변수2"...] 로 단순하다.

    ft_server에서 필요한 패키지들을 다운받는 과정을 RUN 명령문에 작성해야할 것 같다.

    RUN apt-get update && apt-get upgrade && apt-get -y install
    nginx
    curl
    openssl
    vim
    mariadb-server
    php-mysql
    php-mbstring
    wget
    php-fpm

  • CMD

    컨테이너가 시작되고 가장 처음 실행될 명령어를 지정한다.

    하나의 Dockerfile을 만들 때 딱 한번만 쓸 수 있는 명령어이다.
    제일 첫 명령을 지정하는 것이니 당연히 한 번만 사용 가능하다.
    굳이 할 작업이 없다면 사용하지 않아도 관계없는 명령어이다.

    docker run 으로 컨테이너를 생성하거나
    docker start 며령으로 정지된 컨테이너를 재시작시킬 때 동작한다.

    CMD 또한 RUN과 마찬가지로 /bin/sh를 거치지 않고 바로 실행되도록 할 수 있다.

    CMD ["쉘명령어","매개변수1","매개변수2"...]

  • WORKDIR

    RUN,CMD,ENTRYPOINT에서 설정한 실행 파일이 실행될 디렉토리 위치를 지정한다.

    WORKDIR 명령문을 사용한다면

    WORKDIR /srcs 이런 형식으로 사용해야되는걸까?

  • ADD || COPY

    ADD와 COPY는 파일을 이미지에 추가하는 역할을 한다.

    ADD <복사할 파일 경로(호스트)> <파일이 위치할 경로(이미지내부)>

    COPY <복사할 파일 경로(호스트)> <파일이 위치할 경로(이미지내부)> 의 형식을 가진다.

    Dockerfile이 존재하는 경로의 하위경로에 존재하는 파일만 이미지 내부로 넣을 수 있다.

    물론 파일뿐 아니라 하위 디렉토리 자체를 넣을 수도 있으며, *를 사용할 수 있다.

    따라서 Dockerfile을 작성할 때 별도로 파일 저장용 폴더를 하나 만들어놓고 이미지에 옮겨담을 파일들을 미리 모아두면 편하다.

    웹에서 파일을 가져다가 넣을 수도 있다. 파일의 URL을 경로에 그대로 써넣으면 된다.

    또한 경로의 마지막에 /를 붙이면 새로운 디렉토리를 생성하고 그 아래에 파일을 복사한다.

    압축된 tar.* 파일은 자동으로 압축 해제되어 파일만 저장되므로 새로운 디렉토리를 따로 잡아주는게 좋다.

    주의할 점으로는 경로를 입력할 때 반드시 절대경로를 입력해야 한다는 점에 유의한다.

    COPY 는 기능적으로는 동일하나 부가 기능면에서 ADD보다 부족하다. 보다 직관적으로 파일의 복사 자체에만 집중한 명령어로, 경로에 웹사이트 파일 URL을 입력할 수도 없고, 파일의 압축이 저절로 풀리는 기능도 제공하지 않는다.

    srcs 디렉토리 안에 있는 파일들을 ADD 또는 COPY 명령문을 통해 이미지에 추가시키면 될 것 같다.

  • ENV

    ENV 명령은 환경변수를 설정한다. 설정한 환경변수는 RUN, CMD, ENTRYPOINT에 즉각 반영된다.

    마찬가지로 형식은 ENV <환경변수> <값> 이다.

    환경변수는 docker run 명령의 -e 옵션으로도 지정할 수 있다.

    docker run -e <환경변수>=<값> <이미지이름> 의 형식을 가진다.

  • EXPOSE

    EXPOSE는 호스트와 연결할 포트 번호를 설정하는 명령이다.

    동시에 여러개의 포트를 설정할 수도 있다.

    docker run 명령의 --expose 옵션과 동일하다.

    단, EXPOSE는 호스트와 연결하는 포트를 설정할 뿐,

    몇 번 포트가 호스트와 연결되었는가를 공개하지는 않는다.

    호스트와 연결된 포트를 외부에 공개하려면 docker run 명령의 -p 옵션을 사용한다.

  • VOLUME

    VOLUME 명령에 의해 지정된 디렉토리는 컨테이너에 저장하지 않고 호스트에 저장하도록 한다.

    형식은 두 가지를 가진다. 후자는 여러개의 디렉토리를 지정할 때 쓰인다.

    VOLUME <디렉토리>

    VOLUME ["디렉토리1", "디렉토리2"]

    VOLUME 명령은 디렉토리를 호스트와 연결시키는 명령은 아니다.

    이 기능은 docker run 명령의 -v옵션으로 구현되어있다.

    docker run -v <호스트 디렉토리>:<이미지 내부 디렉토리> 이미지이름

    docker run -v /root/tmp:/home/newfolder imagename

  • USER

    명령을 실행할 사용자 계정을 설정하며, RUN, CMD, ENTRYPOINT에 즉각 반영된다.

    USER <사용자계정> 의 형식을 가진다.

  • ONBUILD

    지금까지 하나의 Dockerfile을 생성하는 경우에 대해서만 생각했다면,

    ONBUILD 명령은 조금 더 넓은 개념으로 쓰이는 명령어이다.

    누군가에게는 쓰지 않아도 그만인 명령어일 수 있다.

    위의 과정을 거쳐 생성된 이미지들은 그 자체로 기능을 하기에 문제가 없다.

    그러나 어떤 경우에는 기존에 있는 이미지를 가져다가 일부 수정하여 쓰고 싶은 경우가 있다.

    이 경우 사용하는 명령이 ONBUILD 이다.

    ONBUILD는 이미 생성된 이미지를 기반으로 다른 이미지를 파생시킬 때

    실행할 명령어들을 지정하는 명령어이다.

    즉, 맨 처음 ONBUILD 명령을 입력해서 최초 이미지를 생성한 사람에게는

    ONBUILD 명령이 동작하지 않는다.

  • ARG

    ARG 명령문은 docker build 커맨드로 이미지를 빌드 시, --build-arg 옵션을 통해 넘길 수 있는 인자를 정의하기 위해 사용합니다.

    예를 들어, Dockerfile에 다음과 같이 ARG 명령문으로 port를 인자로 선언해주면,

ARG port

다음과 같이 docker build 커맨드에 --build-arg 옵션에 port 값을 넘길 수가 있습니다.

$ docker build --build-arg port=8080 .

인자의 디폴트값을 지정해주면, --build-arg 옵션으로 해당 인자가 넘어오지 않았을 때 사용됩니다.

ARG port=8080

설정된 인자 값은 다음과 같이 ${인자명} 형태로 읽어서 사용할 수 있습니다.

CMD start.sh -h 127.0.0.1 -p ${port}

완성된 dockerfile을 빌드시키는 명령어는

"docker build -t 디렉토리명/이미지명:태그 빌드할디렉토리" 이다.

ft_server 구동

docker build . -t ft_server

docker run -it --name ft_server -p 80:80 -p 443:443 ft_server

MySQL 서버 연결 오류 문제

run.sh 에서 각 mysql 구문 수행 후

docker bash에서 mysql root 권한에게 패스워드 입력 과정을 스킵하도록 설정

#   run.sh
#!/bin/bash

# 쉘 스크립트 파일 및 var/www 권한 변경
chmod +x ./copy/run.sh
chown -R www-data:www-data /var/www/
chmod -R 755 /var/www/

# OpenSSL 개인 키 & 인증서 생성 및 이동, 권한 변경
openssl req -newkey rsa:4096 -days 365 -nodes -x509 -subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=Lee/CN=localhost" -keyout localhost.dev.key -out localhost.dev.crt
mv localhost.dev.crt etc/ssl/certs/
mv localhost.dev.key etc/ssl/private/
chmod 600 etc/ssl/certs/localhost.dev.crt etc/ssl/private/localhost.dev.key

# Dockerfile에 의해 복사된 default 파일을 nginx 웹 서버에 적용
cp -p ./copy/default /etc/nginx/sites-available/

# 워드프레스 구축
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/wordpress
cp -p ./copy/wp-config.php /var/www/html/wordpress

# mysql 구문을 통해 워드프레스 DB 생성
service mysql start
echo "CREATE DATABASE IF NOT EXISTS wordpress;" | mysql -u root --skip-password
echo "CREATE USER IF NOT EXISTS 'bahn'@'localhost' IDENTIFIED BY '';"  | mysql -u root --skip-password
echo "GRANT ALL PRIVILEGES ON wordpress.* TO 'bahn'@'localhost' WITH GRANT OPTION;" | mysql -u root --skip-password
echo "USE wordpress;"



# phpMyAdmin 구축
wget https://files.phpmyadmin.net/phpMyAdmin/5.0.2/phpMyAdmin-5.0.2-all-languages.tar.gz
tar -xvf phpMyAdmin-5.0.2-all-languages.tar.gz && \
mv phpMyAdmin-5.0.2-all-languages phpmyadmin
mv phpmyadmin /var/www/html/
cp -p ./copy/config.inc.php /var/www/html/phpmyadmin/   # blowfish 암호가 삽입된 srcs/config.inc.php 파일을 복사

service nginx start
service php7.3-fpm start
service mysql restart

bash
//  wp-config.php
...
// ** MySQL settings - You can get this info from your web host ** //
/** The name of the database for WordPress */
define( 'DB_NAME', 'wordpress' );

/** MySQL database username */
define( 'DB_USER', 'bahn' );

/** MySQL database password */
define( 'DB_PASSWORD', '1234' );

/** MySQL hostname */
define( 'DB_HOST', 'localhost' );

/** Database Charset to use in creating database tables. */
define( 'DB_CHARSET', 'utf8' );

/** The Database Collate type. Don't change this if in doubt. */
define( 'DB_COLLATE', '' );
...
//  config.inc.php
...
/**
 * This is needed for cookie based authentication to encrypt password in
 * cookie. Needs to be 32 chars long.
 */
$cfg['blowfish_secret'] = 'IMZt9EC{Dj-wqTUY,oa;1L[5Ydcj{7le';
...
/* Server parameters */
$cfg['Servers'][$i]['host'] = 'localhost';
$cfg['Servers'][$i]['compress'] = false;
$cfg['Servers'][$i]['AllowNoPassword'] = true;
...

MariaDB Unix Socket

MariaDB가 버전 10부터 인증방식에 변화를 주면서

Unix socket 방식을 도입했다고 한다.

이전에는 -u 옵션을 통해 root를 명시하고 로그인을 했다면

sudo로서 root 권한을 가지고 있다는 사실만 증명만 된다면,

다른 인증 과정을 거치지 않고 바로 로그인 접속이 가능하도록 

변화를 주었다고 한다.

그렇기 때문에 이전과 달리 "mysql" 단어만 bash 에서 입력한다면

자동으로 접속되는 모습을 확인할 수 있다.


Dockerfile 문법 정리

Dockerfile 자주 쓰이는 명령문

Dockerfile, /srcs 구성

ft_server MySQL 오류 해결방법

profile
42Seoul-bahn

관심 있을 만한 포스트

0개의 댓글