Docker 사용

......·2024년 1월 29일

42서울

목록 보기
6/7

목표

  • 해당 그림을 유지하도록 docker file을 작성해서 실행시키는게 목적이다.
  • 443포트를 통해서 nginx를 실행시켜 웹사이트를 출력하는 것이며, nginx가 실행되기 위해서는 wordpress가 있어야하고, wordpress를 실행시키기 위해서 db(mariadb)를 구축하는것이다.

Docker란?

<출처 : https://aws.amazon.com/ko/compare/the-difference-between-docker-vm/ | https://aws.amazon.com/ko/docker/>

  • Docker는 애플리케이션을 신속하게 구축, 테스트 및 배포할 수 있는 소프트웨어 플랫폼이다. Docker에서는 소프트웨어를 컨테이너라는 유닛으로 패키징을 해서 관리를 한다.
  • 쉽게 생각하면 게임들의 클라이언트들을 설치한다고 생각하면 된다.
  • 어떠한 환경이던 docker file을 실행시키게 되면 항상 동일한 환경이 구축된다고 생각하면 된다.
  • 컨테이너로 이루어진 방식이 도커의 동작 환경이고, VM(가상머신)으로 이루어진 방식이 가상머신의 동작 환경이다.
  • 가상머신과 도커 모두 이미지를 기반으로 동작하는 것
    • 도커 : 애플리케이션(소프트웨어)의 동작환경을 백업하는 이미지, 따라서 각 컨테이너간에 독립성이 보장 -> 독립성이 보장되기 때문에, 프로그램들의 버전이 달라져도 컨테이너 안의 프로그램과 컨테이너 밖의 프로그램이 서로 영향을 받지 않음
    • 가상머신 : 가상머신의 운영체제의 동작환경을 백업하는 이미지
  • 가상머신과 도커 모두 이동성을 고려해서 설계됨
    • 도커 : 소프트웨어만의 동작환경을 가지고 있는 이미지를 통해 실행되기 때문에 이동하는 파일의 크기가 가상머신에 비해서 작음 / 작업환경을 새로운 곳에 적용하기 위해서 필요한 파일이 적고 가벼움
    • 가상머신 : 전체적인 운영체제의 동작환경을 가지고 있는 이미지를 통해 실행되기 떄문에 이동하는 파일의 크기가 보다 큼(운영체제의 이미지를 전부 가지고 있어야지 동작) / 작업환경을 새로운 곳에 적용하기 위해서는 세팅을 일일히 해야하며 필요한 파일이 많음
  • 운영 주체
    • 도커 : 도커엔진과 OS를 통해 관리가 이루어짐
    • 가상머신 : 하이퍼바이저 영역에서 물리적인 하드웨어와 가상머신이 관리
  • Docker 설치(리눅스 기준)
    • 설치하고자 하는 OS의 터미널환경에서 apt-get install docker.io를 하게 되면 그 os에서 설치가 가능한 버전의 도커가 설치가 되게됨
    • 설치 후, docker -v를 통해서 버전을 확인할 수 있음

Docker-Compose 란?

  • 앞서 말한 도커의 각각의 컨테이너를 docker-compose.yml이라는 파일을 통해서 하나의 전체적인 컨테이너로 묶어서 실행시키는 것
  • yml파일을 통해서 각 docker file(도커 이미지파일)을 묶어서 하나의 컨테이너로 동작하는 것
  • docker-compose를 사용하지 않는다면, docker로 많은 프로세스들을 실행시켜야 할 경우, 하나하나의 이미지를 실행시켜서 묶어줘야한다는 번거로운 작업이 필요해짐
  • Docker-compose 설치
    1. DOCKER_CONFIG={DOCKER_CONFIG:-HOME/.docker} -> 도커가 설치될 위치를 환경변수로 미리 설정
    2. mkdir -p $DOCKER_CONFIG/cli-plugins -> 도커가 설치될 폴더 및 플러그인을 해줄 폴더를 생성
    3. curl -SL https://github.com/docker/compose/releases/download/v2.24.2/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose -> 도커의 버전을 설치하는 것으로, 원하는 버전을 vx.xx.x위치에 넣어주면 된다. (만일 curl이 설치되어 있지 않을 경우, apt-get install curl을 통해서 설치를 하고 3번 명령어를 실행시켜주면 됨)

Docker file 작성법

  • Docker Hub에 설치하고자 하는 프로그램들을 검색하면 대부분 찾아볼 수 있음
  • FROM : 도커의 설치 OS환경을 물어보는 것으로 debian:bullseye 을 작성하면 데비안의 bullseye버전을 사용하겠다는 것
  • EXPOSE : port번호 설정
  • COPY : 복사하고자 하는 파일 | 복사후 위치 파일
  • RUN : 안에 있는 내용들이 실제 터미널에서 실행된다고 생각하면 됨
  • ENTRYPOINT : 컨테이너가 실행되고 최초로 실행할 명령어를 입력하는 부분으로 ["실행시킬 프로그램", "이름"] 으로 작성을 해주면 컨테이너가 실행 시, "프로그램"을 통해 "이름"파일을 실행
  • WORKDIR : 도커가 작업할 디렉토리를 설정

Mariadb

  • mariadb의 conf파일을 요구사항에 맞게 변경을 해줘야함
user                    = mysql
pid-file                = /run/mysqld/mysqld.pid
socket                  = /run/mysqld/mysqld.sock
#port                   = 3306
basedir                 = /usr
datadir                 = /var/lib/mysql
tmpdir                  = /tmp
lc-messages-dir         = /usr/share/mysql
.....
bind-address            = 0.0.0.0
  • 이렇게 바꿔주고 conf파일을 따로 가지고 도커파일에서 COPY ./conf/50-server.cnf /etc/mysql/mariadb.conf.d/ 로 작성해주면 도커 실행시, 파일이 변경이 됨

  • sh파일세팅

flush privileges;
create database $MYSQL_DB;
create user '$MYSQL_USER'@'%' identified by '$MYSQL_PASSWORD';
grant all privileges on $MYSQL_DB.* to '$MYSQL_USER'@'%';
alter user '$MYSQL_ROOT'@'localhost' identified by '$MYSQL_ROOT_PASSWORD';
flush privileges;
  • 환경변수로 지정된 DB를 생성하고, 그 DB에 USER와 PASSWORD를 설정해주고, ROOT계정도 설정을 해주는 부분

NGINX

  • openssl을 통해서 구동을 하며, 현재 사용되는 프로토콜중 하나
  • openssl에서 TSLv1.2 TSLv1.3을 사용하는 것이며, 각각의 프로토콜은 암호화 프로토콜중 하나
  • TSL의 암호화 프로토콜을 사용하게 되면, 웹사이트를 접근할 때, http가 아닌 https로 접근하는것
  • 이를 세팅하는 것이 아래와 같이 conf파일을 세팅하는것
server {
    listen 443 ssl;

    server_name seykim.42.fr;

    ssl on;
    ssl_protocols  TLSv1.2 TLSv1.3;
    ssl_certificate_key /etc/ssl/seykim.42.fr.key;
    ssl_certificate /etc/ssl/seykim.42.fr.crt;

    index index.html index.htm index.php;

    root /var/www/html;

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

    location ~ \.php {
        # php interpreter (aka Wordpress container)에게 위임.
        fastcgi_pass wordpress:9000;
        fastcgi_split_path_info ^(.+\.php)(.*)$;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include fastcgi_params;
    }
}
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; document_root
# FastCGI 서버에 전송되는 환경 변수인 SCRIPT_FILENAME을 설정합니다.
# $document_root는 현재 서버의 문서 루트 디렉토리 -> 위의 root /var/www/html
# $fastcgi_script_name은 FastCGI 서버로 전송되는 스크립트 파일의 경로 SCRIPT_FILENAME


# fastcgi_param PATH_INFO $fastcgi_path_info;
# FastCGI 서버에 전송되는 환경 변수인 PATH_INFO를 설정합니다.
# $fastcgi_path_info는 클라이언트가 요청한 URL에서 스크립트 파일을 제외한 추가 경로 정보를 나타내며, 이 정보는 FastCGI 서버로 전달되어 동적인 콘텐츠 생성에 활용
# FastCGI 프로토콜을 통해 백엔드의 FastCGI 서버 (예: PHP-FPM)로 전달할 때 필요한 환경 변수를 설정하는 데 사용
  • 443포트를 통해서 ssl통신을 하겠다는 것

  • ssl에서 프로토콜로 TLSv1.2 TLSv1.3을 쓰겠다는 것이며, 각각의 통신을 위한 인증키를 /etc/ssl/ 위치에서 찾아오겠다는 것

  • index -> 처음에 볼륨에서 가지고 있는 데이터들이 저장된 파일

  • FastCGI프로토콜 -> 프로그램을 웹 서버와 통신하기 위한 바이너리 프로토콜 정도로만 알고 있으면 될 것 같음

  • sh파일 설정

openssl req -newkey rsa:4096 -days 30 -nodes -x509 \
    -subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=${COALITIONS}/CN=${INTRA_ID}.42.fr" \
    -keyout "/etc/ssl/${INTRA_ID}.42.fr.key" \
    -out "/etc/ssl/${INTRA_ID}.42.fr.crt" 2>/dev/null
  • openssl req: OpenSSL 명령어 중 하나로, 새로운 인증서 요청(Certificate Signing Request, CSR) 및 관련 키를 생성하거나 처리합니다.

  • newkey rsa:4096: RSA 알고리즘을 사용하는 4096 비트의 새로운 개인 키를 생성

  • rsa : RSA암호는 공개키 암호시스템의 하나로, 암호화뿐만 아니라 전자서명이 가능한 최초의 알고리즘

  • days 30: 생성된 자체 서명된 인증서의 유효 기간을 30일로 설정

  • nodes: 개인 키를 암호화하지 않음

  • x509: X.509 표준에 따라 서명된 자체 서명된 인증서를 생성 / x.509표준은 공개키 인증서와 인증알고리즘의 표준 가운데에서 공개 키 기반(PKI)의 ITU-T 표준을 쓰는 것

  • 아래가 x509표준의 형식

Certificate
Version 인증서의 버전을 나타냄
Serial Number CA가 할당한 정수로 된 고유 번호
Algorithm Identifier 알고리즘 식별자
Signature 서명
Issuer 발행자
Validity 유효기간
Not Before 유효기간 시작 날짜
Not After 유효기간 끝나는 날짜
Subject 소유자
Subject Public Key Info 소유자 공개 키 정보
Public Key Algorithm 공개 키 알고리즘
Subject Public Key
Issuer Unique Identifier (Optional) 발행자 고유 식별자
Subject Unique Identifier (Optional) 소유자 고유 식별자
Extensions (Optional) 확장
...
Certificate Signature Algorithm
Certificate Signature
  • subj "/C=KR/ST=Seoul/L=Seoul/O=42Seoul/OU=COALITIONS/CN={COALITIONS}/CN={INTRA_ID}.42.fr": 인증서의 주체(subject) 필드를 설정

  • keyout "/etc/ssl/${INTRA_ID}.42.fr.key": 생성된 개인 키를 /etc/ssl/ 디렉터리에 ${INTRA_ID}.42.fr.key 파일로 저장

  • out "/etc/ssl/${INTRA_ID}.42.fr.crt": 생성된 자체 서명된 인증서를 /etc/ssl/ 디렉터리에 ${INTRA_ID}.42.fr.crt 파일로 저장

  • 2>/dev/null: 표준 에러를 무시하도록 설정

WORDPRESS

  • 도커파일에서 RUN파트에 chmod 777 /var/www를 줘야지 워드프레스에 사진이 올라감(권한을 설정하지 않으면 사진이 올라가지 않음)
  • COPY ./conf/www.conf /etc/php/7.4/fpm/pool.d/www.conf
    이렇게 conf파일을 바꿔줄 것인데
listen = wordpress:9000
  • 이 부분만 바꿔주면 됨 -> 9000포트를 통해서 통신하겠다는 설정

  • sh파일 작성

wp-cli core download --allow-root
-> 워드프레스의 코어를 다운로드, root로 실행할 때 사용 권한 문제를 허용
wp-cli config create --dbname=$MYSQL_DB --dbuser=$MYSQL_USER --dbpass=$MYSQL_PASSWORD --dbhost=$MYSQL_HOST --allow-root
-> wp-config.php파일을 생성하고 데이터베이스 관련 정보를 설정
wp-cli core install --url=$DOMAIN_NAME --title=$WP_TITLE --admin_user=$WP_ADMIN_USER --admin_password=$WP_ADMIN_PASSWORD --admin_email=$WP_ADMIN_EMAIL --skip-email --allow-root
-> url : 주소설정, title : 제목 설정, admin 관련 : 관리자 계정 설정
wp-cli user create $WP_USER $WP_USER_EMAIL --user_pass=$WP_USER_PASSWORD --role=subscriber --allow-root
-> role : 사용자 역할 설정

Docker-compose.yml파일

# 버전을 정의
version: '3.8'


# 각 서비들의 정의
services:
  mariadb:
  	# 컨테이너 이름
    container_name: mariadb
    # 도커 허브에서 mariadb의 이미지를 사용
    image: mariadb
    # 컨테이너가 종료되면 항상 재시작을 하도록 설정
    restart: always
    # 해당 위치에서 mariadb를 빌드하도록 설정
    build: requirements/mariadb/
    # 호스트와 연결할 포트 설정
    expose:
            - "3306"
    # MariaDB 데이터베이스 파일을 호스트 디렉터리와 공유합니다
    volumes:
            - mariadb-volume:/var/lib/mysql
    # 내부 네트워크를 사용하도록 설정
    networks:
            - intra-network
    # 환경변수 파일 지정
    env_file:
            - .env
  wordpress:
  	# mariadb가 먼저 실행되어야지 실행됨을 의미
    depends_on:
      - mariadb
    restart: always
    build: requirements/wordpress
    container_name: wordpress
    image: wordpress
    expose:
            - "9000"
    volumes:
            - wordpress-volume:/var/www/html
    networks:
            - intra-network
    env_file:
            - .env
  nginx:
  	# wordpress가 항상 먼저 시작되어야함을 의미
    depends_on:
            - wordpress
    restart: always
    build: requirements/nginx
    container_name: nginx
    image: nginx
    # 컨테이너의 443포트와 호스트의 443포트를 연결
    ports:
            - "443:443"
    volumes:
            - wordpress-volume:/var/www/html
    networks:
            - intra-network
    env_file:
            - .env
# 사용자 네트워크의 정의
networks:
   intra-network:
   			# driver: bridge: 사용자 정의 네트워크를 브릿지(bridge) 모드로 설정
            # 브릿지 네트워크는 동일한 호스트에 있는 컨테이너 간의 통신을 지원
           driver: bridge
           name: intra-network
# 볼륨 설정
volumes:
   mariadb-volume:
   			# 로컬 드라이버로 볼륨을 설정
           driver: local
           driver_opts:
           			# 볼륨의 유형을 'none'
                   type: none
                 	# bind옵션 지정
                   o : bind
                    # 볼륨을 호스트 디렉터리에 바인딩
                    # 즉, 호스트 디렉터리와 컨테이너 내의 볼륨이 공유
                   device : /home/seykim/data/mariadb
   wordpress-volume:
                driver: local
                driver_opts:
                        type: none
                        o: bind
                        device: /home/seykim/data/wordpress

기타 알아둬야하는 내용

  • docker에서의 volume : 하드디스크의 내용이라고 이해를 하면 편함, 즉, 컨테이너의 데이터들이 볼륨에 저장이 되면, 해당 볼륨을 지우지 않는 한, 컨테이너의 내용이 유지가 됨 -> 만약 docker stop nginx를 통해서 컨테이너를 중지시키고 다시 make를 하게 될 경우 volume이 삭제된게 아니기 때문에 이전에 작성했던 내용이 남아있음
  • docker의 mariadb에서 로그인 유저 확인하기
# docker 컨테이너에 접근
docker exec -it nginx /bin/bash
# mysql에 접근
sudo mysql -u root -p
# 비밀번호 입력
-> 설정한 비밀번호 입력
# mariadb에 접근
use MARIADB
# 데이터베이스에서 접근 가능한 유저를 확인
show tables;
select * from wp_users
-> admin계정에서 user를 추가하고 select문을 실행시키면 추가가 된 것을 볼 수 있음
-> 마찬가지로 admin계정에서 user를 삭제하고 select문을 실행시키면 삭제가 된 것을 볼 수 있음

Makefile

HOSTS_SETUP_SH=./srcs/requirements/tools/host.sh
VOLUME_SETUP_SH=./srcs/requirements/tools/volume.sh
FCLEAN_SETUP_SH=./srcs/requirements/tools/fclean.sh
TOOLS_SH_PATH = ./srcs/requirements/tools/ 

DOCKER_COMPOSE_FILE = ./srcs/docker-compose.yml
DOCKER_COMPOSE = docker compose --file $(DOCKER_COMPOSE_FILE)

all: up

up:
	@chmod +x $(VOLUME_SETUP_SH)
	@chmod +x $(HOSTS_SETUP_SH)
	@chmod +x $(addsuffix info.sh, $(TOOLS_SH_PATH))
	@chmod +x $(addsuffix fclean.sh, $(TOOLS_SH_PATH))
	@$(VOLUME_SETUP_SH)
	@$(HOSTS_SETUP_SH)
	$(DOCKER_COMPOSE) up -d --build

down:
	$(DOCKER_COMPOSE) down --volumes

clean:
	sudo docker compose -f srcs/docker-compose.yml down -v --rmi all --remove-orphans
	$(DOCKER_COMPOSE) down --rmi all --volumes

fclean: clean
	sudo rm -rf ${HOME}/data
	sudo docker system prune --volumes --all --force
	sudo docker network prune --force
	sudo docker volume prune --force
	@$(FCLEAN_SETUP_SH)

re:
	@make fclean
	@make all

.PHONY: all up down clean fclean re
  • all: up 명령을 실행합니다.
  • up: 컨테이너를 빌드하고 실행
  • down: 컨테이너를 중지하고 관련된 볼륨을 제거
  • clean: 모든 컨테이너 및 볼륨을 중지하고 제거
  • fclean: clean을 실행하고, 추가로 시스템에서 사용한 Docker 데이터와 네트워크, 볼륨을 제거

공유폴더 설정(리눅스 기준)

  • virtual box에서 설정 -> 공유폴더 설정 -> 공유하고자 하는 폴더를 설정하고 자동 마운트를 설정
  • 왼쪽 상단 메뉴의 Devices/Insert guest additions CD images를 누름
  • /media 폴더에서 공유하고자하는 폴더가 생성이 되었을 것 -> sf*로 설정되었을 것임
  • 실제 설정한 폴더에서 설정이 되었는지 확인해보고 만일 안되었을 경우
mount /dev/cdrom /cdrom/
cd cdrom
./VBoxLinuxAdditions.run
실행시키면 media에 설정되어있음

SSH설정

  • apt-get install openssh-server 설치
  • ssh-keygen 을 통해서 ssh키 생성
  • virtaul box에서 포트포워딩 진행 -> host(127.0.0.1) 게스트는 비워둠 / 포트 host(2222) 게스트(22)설정
systemctl enable ssh // 먼저 해야 sshd_config가 생김
vim /etc/ssh/sshd_config //PermitRootLogin을 yes로 바꾼다.
systemctl restart ssh
  • 설정 후, ssh 이름@127.0.0.1 -p 2222로 하고 password는 설정한 것으로 입력해서 ssh연결 확인

0개의 댓글