42 : Inception 서브젝트와 튜토리얼까지!
 

Inception 과제 해석

Inception



요약:

시스템 관리 관련 연습입니다.



   목차

I 전문
II 소개
III 일반적인 지침들



Chapter I : 전문





Chapter II : 소개


이 프로젝트는 Docker를 사용하여 시스템 관리에 대한 지식을 넓히는 것을 목표로 합니다.

여러 Docker image를 가상화하여 새 개인 가상 머신에서 생성합니다.




Chapter III : 일반적인 지침들


이 프로젝트는 가상머신에서 실행되어야만 합니다.

프로젝트 구성에 필요한 파일들은 모두 [inception/srcs] 폴더에 있어야 합니다.

Makefile이 필요하며, 디렉토리의 루트[inception/]에 있어야 합니다.

Makefile은 전체 어플리케이션을 설정애야 합니다. (docker-compose를 사용하여 Docker 이미지 빌드)

배경에 따라 아직 배우지 않았을 수 있는 개념을 연습합니다.

따라서 Docker 사용과 관련된 많은 문서들을 읽는 데 주저하지 마세요.




Chapter IV : 필수 파트


- 이 프로젝트는 특정한 규칙에 따라 서로 다른 서비스로 구성된 소규모 인프라를 설정합니다.

- 전체 프로젝트는 가상머신에서 수행되어야 하며, docker-compose를 사용하여야 합니다.

- 각 Docker 이미지는 해당 서비스와 동일한 이름을 지녀야 합니다.

- 또한 각 서비스는 전용 컨테이너에서 실행되어야 합니다.

- 성능 문제를 위해 컨테이너는 Alpine Linux의 두번째 버전 또는 Debian buster에서 빌드해야 합니다.
     선택의 당신의 것!

- 서비스 당 하나의 고유한 Dockerfile을 작성해야 합니다.
     Dockerfile은 Makefile에 의해 docker-compose.yaml에서 호출되어야 합니다.
     즉, 프로젝트의 Docker 이미지를 직접 빌드해야 합니다.
     Dockerhub, 기성품 Docker 이미지를 가져오는 것 등은 금지됩니다. (Alpine/Debian 제외).

- 다음의 내용을 설정하세요.

      : TLSv1.2 또는 TLSv1.3만 포함된 Nginx를 구성하는 컨테이너

      : Nginx 없이 Wordpress + php-fpm(설치 및 구성해야 됨)을 구성하는 컨테이너

      : Nginx 없이 MariaDB만 포함하는 컨테이너

      : Wordpress 데이터베이스가 포함된 볼륨

      : Wordpress 웹 사이트 파일이 포함된 두 번째 볼륨

      : 컨테이너 간의 연결을 설정하는 도커 네트워크

- crash가 발생할 경우 재시작 해야 합니다.


info
 
 

Docker 컨테이너는 가상 머신이 아닙니다.
따라서 실행할 때’tail -f’등을 기반으로하는 해키 패치를 사용하지 않는 것이 좋습니다.
데몬의 작동 방식과 사용하는 것이 좋은지 여부에 대해 읽어보십시오.


warn
 
 

당연하게도 [network : host], [--link] 또는 [links :]의 사용은 금지되어 있습니다.
네트워크 라인은 docker-compose.yml 파일에 있어야합니다.
컨테이너는 무한 루프를 실행하는 명령으로 시작되지 않아야 합니다.
마찬가지로, 진입점으로 사용되거나 진입점 스크립트에서 사용되는 모든 명령에도 적용됩니다.
다음은 몇 가지 금지 된 해키 패치입니다 : tail -f, bash, sleep infinity, while true.


info
 
 

PID 1 및 Dockerfile 작성을 위한 모범 사례를 읽어보십시오.


- 당신의 워드프레스 데이터베이스는 두 개의 유저가 있어야 하며, 그 중 하나는 관리자입니다.
     관리자의 이름에는 admin/Admin/administrator/Administrator 등이 포함될 수 없습니다.      ex: admin, administrator, Administrator, admin-123, 등


info
 
 

당신의 볼륨은 Docker를 사용하는 호스트 머신의 /home/login/data 폴더에서 사용할 수 있습니다.
물론 로그인을 당신의 것으로 바꿔야합니다.


- 더 간단하게 하려면, 도메인 이름이 로컬 IP 주소를 가리키도록 구성해야 합니다.
     이 도메인 이름은 [login.42.fr]이어야 합니다. 다시 말하지만, 당신의 로그인을 사용하세요.
     만약 당신이 wil이라면 [wil.42.fr은 wil]의 웹 사이트를 가르키는 IP 주소로 리다이렉션 되어야 합니다.


warn
 
 

최신 태그는 금지되며, Dockerfile에 비밀번호가 없어야합니다.
반드시 환경 변수를 사용해야 합니다. .env 파일을 사용하여 저장하는 것을 추천합니다.
.env 파일은 srcs 디렉토리의 루트에 있어야합니다.
NGINX 컨테이너는 TLSv1.2 또는 TLSv1.3 프로토콜을 사용하여,
포트 443을 통해서만 인프라에 대한 유일한 진입 점이어야합니다.


여기 기대되는 결과값의 예시 다이어그램이 있습니다!


다음은 예상되는 디렉토리 구조의 예입니다:

	
	$> ls -alR
	total XX
	drwxrwxr-x 3 wil wil 4096 avril 42 20:42 .
	drwxrwxrwt 17 wil wil 4096 avril 42 20:42 ..
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 Makefile
	drwxrwxr-x 3 wil wil 4096 avril 42 20:42 srcs
	./srcs:
	total XX
	drwxrwxr-x 3 wil wil 4096 avril 42 20:42 .
	drwxrwxr-x 3 wil wil 4096 avril 42 20:42 ..
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 docker-compose.yml
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 .env
	drwxrwxr-x 5 wil wil 4096 avril 42 20:42 requirements
	./srcs/requirements:
	total XX
	drwxrwxr-x 5 wil wil 4096 avril 42 20:42 .
	drwxrwxr-x 3 wil wil 4096 avril 42 20:42 ..
	drwxrwxr-x 4 wil wil 4096 avril 42 20:42 bonus
	drwxrwxr-x 4 wil wil 4096 avril 42 20:42 mariadb
	drwxrwxr-x 4 wil wil 4096 avril 42 20:42 nginx
	drwxrwxr-x 4 wil wil 4096 avril 42 20:42 tools
	drwxrwxr-x 4 wil wil 4096 avril 42 20:42 wordpress
	./srcs/requirements/mariadb:
	total XX
	drwxrwxr-x 4 wil wil 4096 avril 42 20:45 .
	drwxrwxr-x 5 wil wil 4096 avril 42 20:42 ..
	drwxrwxr-x 2 wil wil 4096 avril 42 20:42 conf
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 Dockerfile
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 .dockerignore
	drwxrwxr-x 2 wil wil 4096 avril 42 20:42 tools
	[...]
	./srcs/requirements/nginx:
	total XX
	drwxrwxr-x 4 wil wil 4096 avril 42 20:42 .
	drwxrwxr-x 5 wil wil 4096 avril 42 20:42 ..
	drwxrwxr-x 2 wil wil 4096 avril 42 20:42 conf
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 Dockerfile
	-rw-rw-r-- 1 wil wil XXXX avril 42 20:42 .dockerignore
	drwxrwxr-x 2 wil wil 4096 avril 42 20:42 tools
	[...]
	$> cat srcs/.env
	DOMAIN_NAME=wil.42.fr
	# certificates
	CERTS_=./XXXXXXXXXXXX
	# MYSQL SETUP
	MYSQL_ROOT_PASSWORD=XXXXXXXXXXXX
	MYSQL_USER=XXXXXXXXXXXX
	MYSQL_PASSWORD=XXXXXXXXXXXX
	[...]
	$>
	

참고자료

inception은 새로 생긴 과제라서 42 reference가 하나도 없습니다.

따라서 docker-compose 자체를 공부!

Mi crosoft - Docker compose 사용하기 평범한개발자노트 - 도커 컴포즈 네트워크 daleseo - 도커 컴포즈 네트워크 생활코딩 - Nginx, MySQL, php-fpm

Infrearn 강의 : 도커 쓸 땐 필수! 도커 컴포즈 by 너굴

inflearn.com/course/도커-컴포즈

해당 강의를 듣고 정리한 내용입니다.

21강에 총합 약 50분이며, 36,300원입니다.


도커 컴포즈 소개

도커가 사람들에게 많은 각광을 받았습니다.

당연하게도 사람들은 도커의 불편한 점들을 개선하기 위해 많은 노력을 하였는데, 그 중 대표주자가 Fig입니다.

Fig는 Docker에서 자주 사용하고 길어지는 명령어를 치는 것이 불편하다고 생각하여 만들어졌습니다.

그러나 이후 Fig가 나름의 유명세를 타게 되면서, 2015년 Docker-compose로 흡수되게 됩니다.


일반적인 도커는 Dockerfile이 Image를 빌드하고, Image가 Container를 실행시키는 방식으로 제작됩니다.

여기서 Config라는 부분을 넣어 포트, 볼륨 등을 설정으로서 추가할 수 있도록 Docker-compose 입니다.

Docker-compose는 docker-compose.yml이라는 파일에 이 내용들을 넣어놓고, 간단한 명령어로 하여금 실행시킬 수 있도록 제작되었습니다.

심지어 여러 컨테이너를 컨트롤 할 수도 있도록 되었습니다.




docker-compose 설치

만약 가상 머신(Ubuntu)를 사용중이라면, 다음의 명령어로 설치합시다.

# docker 설치
curl -fsSL https://get.docker.com/ | sudo sh
sudo usermod -aG docker $USER
				
# docker-compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

termianl로 설치하고 싶지 않다면, 그냥 Docker for Desktop을 설치하여도 됩니다.

이제 잘 설치되었나 확인해봅시다.

docker-compose version

원한다면 alias 등을 사용해서 docker-compose 긴 명령을 축약해서 사용해도 됩니다.

alias dco='docker-compose'

그럼 이제 본격적으로 장점을 알아봅시다.

1. 긴 docker 실행 명령어를 단축

다음은 nginx를 docker로 실행하는 방법입니다.

nginx 컨테이너 실행

docker run -it nginx

참고: 이 방법은 docker ps로만 실행중인지 확인할 수 있습니다.

nginx 컨테이너 실행 + Host 8080 port 연결

docker run -it -p 8080:80 nginx

nginx 컨테이너 실행 + Host 8080 port 연결 + 종료시 자동삭제

[주소][localhost:8080]으로 접속하면 nginx 페이지가 나옵니다. [주소][localhost]는 안됨!

이건 종료 후 [명령어][docker ps -a]를 통해 실행중임을 확인할 수 있습니다.

docker run -it -p 8080:80 --rm nginx

nginx 컨테이너 실행 + Host 8080 port 연결 + 종료시 자동삭제 + Host Directory를 컨테이너 안에 링크

# /[project folder]/nginx/index.html

	<html>
		<head>
		</head>
		<body>
			<h1>HELLO, DOCKER_COMPOSE!</h1>
		</body>
	</html>
docker run -it -p 8080:80 --rm -v $(pwd):/usr/share/nginx/html/ nginx
warn
 
 

주의: index.html이 있는 디렉토리에서 명령어를 실행하여야 합니다.
아니면 403 Forbidden..

여기서만 봐도 docker run 명령어가 매우 길어진 것을 확인 할 수 있습니다.

컨테이너끼리의 간편한 연결

django 컨테이너와 postgres 컨테이너가 필요합니다.

다음 명령어를 이용하여 django-sample을 설치합시다.

git clone https://github.com/raccoonyy/django-sample-for-docker-compose.git django-sample
cd django-sample
docker build -t django-sample .
# -d 옵션은 컨테이너를 detached 모드에서 실행시키는 것으로(background로 실행), 컨테이너 ID를 결과값을 출력합니다.
docker run --rm -d --name django -p 8000:8000 django-sample

실행되셨나요? 실행되었다면 이상한 긴 문자열 하나만 뱉은 뒤 localhost:8000에서의 django를 보실 수 있을겁니다.

# -e 옵션은 환경변수를 출력합니다. 참고: dockerfile의 ENV 설정도 덮어씌웁니다.
docker run --rm -d --name postgres -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres

이렇게 실행하면 django와 postgres가 연결되지 않습니다.

일단 실행시킨 아이들을 삭제시켜주세요..

info
 
 

컨테이너를 삭제/중지하기 위해서는 docker kill이나 docker stop을 이용하시면 됩니다

그럼 이번에는 제대로 실행해 보겠습니다.

먼저 postgres를 그대로 실행시킵니다.

docker run --rm -d --name postgres -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres

그 다음에 django sample을 실행시킵니다.

명령어가 조금 바뀌었으니 바뀐 명령어를 이용하세요!

docker run --rm -d -p 8000:8000 -e DJANGO_DB_HOST=db --link postgres:db django-sample

이제 잘 실행된답니다.


해결 못한 궁금증

강의에선 분명 첫번쨰 방법으로 django -> postgres순으로 실행시켰을 때 연결 거부 메시지가 떴습니다.

질문글도 하나 올라 올라와있는데, 저처럼 django -> postgres순으로 실행해도 django 페이지가 뜬다고 하네요.

왜 이런지 모르겠는데, 버전 차이나 뭐 그런게 아닐까 지레짐작해봅니다

특정 컨테이너끼리만 통신하는 가상 네트워크 환경을 편하게 구성할 수 있음

postgres를 실행합시다

docker run --rm -d --name postgres -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres

다음에는 django를 django1이라는 이름으로 실행해봅시다.

docker run --rm -d --name django1 -p 8000:8000 -e DJANGO_DB_HOST=db --link postgres:db django-sample

이번에는 django를 django2라는 이름으로 실행합니다. (주의: 포트가 8001입니다)

docker run --rm -d --name django2 -p 8001:8000 -e DJANGO_DB_HOST=db --link postgres:db django-sample

8000, 8001 모두 반가운 로켓이 반겨줄겁니다!

이런 식으로 실행하면 postgres 컨테이너의 보안성이 취약해진다는 것을 알 수 있습니다.

호스트에서 Docker Container 실행 권한이 있다면 누구나 postgres에 접근할 수 있는 것이니까요.

이걸 관리하기 위해 docker network 기능을 사용합니다.

먼저 다음 명령어를 실행해봅시다.

docker network ls

bridge, host, none 네트워크가 저희를 반깁니다.

저희만의 네트워크를 만들어보겠습니다. 이름은 web-service, 드라이버는 bridge입니다.

docker network create --driver bridge web-service

이제 docker network ls를 실행하면 web-service 네트워크가 생긴 것을 확인할 수 있습니다.

network의 기능을 확인하기 위해, web-service 안에 postgres, django1을 실헹시키고 django2도 실행시킵니다.

docker run --rm -d --name postgres --network web-service -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres
docker run --rm -d --name django1 --network web-service -p 8000:8000 -e DJANGO_DB_HOST=db --link postgres:db django-sample
docker run --rm -d --name django2 -p 8001:8000 -e DJANGO_DB_HOST=db --link postgres:db django-sample

postgres와 django1은 정상작동하여 로켓잼을 만날 수 있지만 불행히도 django2는 나-락간 것을 볼 수 있습니다..

docker: Error response from daemon: Cannot link to /postgres, as it does not belong to the default network.

끝났으니 docker network rm web-service를 통해 삭제하세요.

정리

도커를 사용하면서 생기는 복잡성, 네트워크를 통한 관리 등을 간편하게 하기 위해 docker-compose를 사용합니다.

길어진 명령어를 설정 형태로 docker-compose.yml 파일에 저장합니다.

이 파일이 복잡하고 어려워보일 수 있지만, 한 번 작성하면 잘 바뀌지 않으며 훨씬 더 이해하기 쉽습니다.

앞의 내용을 간단하게 정리해보겠습니다.

# 실행 명령어 나열
docker network create --driver bridge web-service
docker run --rm -d --name postgres --network web-service -e POSTGRES_DB=djangosample -e POSTGRES_USER=sampleuser -e POSTGRES_PASSWORD=samplesecret postgres
docker run --rm -d --name django --network web-service -p 8000:8000 -e DJANGO_DB_HOST=db --link postgres:db django-sample

# 종료 명령어 나열
docker kill django1 postgres
docker network rm web-service

docker-compose.yml

version: '3'

volumes:
  postgres_data: {}

services:
  db:
    image: postgres
    volumes:
      - postgres_data:/var/lib/postgres/data
    environment:
      - POSTGRES_DB=djangosample
      - POSTGRES_USER=sampleuser
      - POSTGRES_PASSWORD=samplesecret

  django:
    build:
      context: .
      dockerfile: ./compose/django/Dockerfile-dev
    volumes:
      - ./:/app/
    command: ["./manage.py", "runserver", "0:8000"]
    environment:
      - DJANGO_DB_HOST=db
    depends_on:
      - db
    restart: always
    ports:
      - 8000:8000 

다음 명령어로 실행/종료하세요.

# 실행
docker-compose up -d

# 종료
docker-compose down

실습1: nginx 서버 도커 컴포즈로 실행하기

정보 내용
이미지 nginx:latest
Listening Port 80
HTML 경로 /usr/share/nginx/html

호스트의 60080 포트를 컨테이너의 80 포트로 연결!

index.html 파일을 만들고, NGINX 접속시 이 파일이 나타나도록!

[주소][localhost:60080]로 접속해야 index를 볼 수 있습니다.

nginx 서버 docker run으로 실행하기

더보기
# -v 옵션은 Host와 Container간의 볼륨 설정을 위해 사용됩니다. Host PC의 파일 시스템의 경로에서 마운트 해줍니다.
docker run -itd -p 60080:80 -v $(pwd):/usr/share/nginx/html/ nginx

종료하려면 docker kill [names]

nginx 서버 docker compose으로 실행하기

다음 docker-compose.yml의 빈칸을 작성하여 nginx 서버를 실행하세요.

version: '3'

services:
  nginx:
  image: ()
  ports:
    - ():()
  volumes:
    - ():()
더보기
version: '3'

services:
  nginx:
    image: nginx:latest
    ports:
      - 60080:80
    volumes:
      - ./:/usr/share/nginx/html/

종료하려면 docker kill [namges]

YML 작성

간단한 문법들

- 확장자: [name.yml] 또는 [name.yaml]

- 키와 값은 : 기호

- 블록이 올 때 두 칸 띄어쓰기

- 목록은 - 기호로

- 주석은 # 기호로

docker-compose.yml 파일 명령어

version

docker-compose.yml의 버전을 지정합니다.

어떤 버전을 쓰냐에 따라 지원하는 도커 엔진의 버전이 달라집니다.

강의 중에선 주로 '3'을 사용하며 현재 3.9까지 나온 거로 알고 있습니다.

services

어떤 컨테이너를 실행하는지를 정의합니다.

앞에서 postgres, django를 지정한 서비스도 이것이며,

docker run --name ~~과 같다고 생각할 수 있습니다.

image

어떤 컨테이너를 실행할지 정의합니다.

기존에 등록되어있는 이미지를 불러오며, inception에서는 사용해서는 안됩니다. (build 사용)

만약 이미지가 없다면, 자동으로 pull받습니다. (up 할때 함)

build

image를 자체 빌드하여 사용하는 방법입니다.

image 속성 대신 사용하며, 별도의 Dockerfile이 필요합니다.

ports

컨테이너와 연결할 포트를 지정합니다.

"호스트_포트:컨테이너_포트"로 지정하며, docker run의 -p 옵션과 동일합니다.

environment

컨테이너에서 사용할 환경변수(아이디, 비밀번호 등등)를 지정합니다.

"환경변수_이름=값"의 형태로 사용하며, docker run의 -e 옵션과 동일합니다.

저희는 사용해서는 안되며, 대신 env_file: .env을 이용하여 외부 파일에 기술해 놓습니다.

volumes

마운트하는 디렉토리를 지정합니다.

"호스트_디렉터리:컨테이너_디렉터리"로 지정하며, docker run의 -v 옵션과 동일합니다.

link

다른 컨테이너와 연결할 때 사용합니다.

docker compose 내에서 컨테이너들이 연결되기 때문에 일반적으로 사용하지 않습니다..

"연결할_컨테이너_이름:컨테이너에서_참조할_이름"로 지정합니다.

depends_on

컨테이너에 의존성을 추가하여 실행순서를 제어합니다.

실습2 - docker compose로 wordpress, mysql 서버 실행하기

Wordpress 컨테이너

설정 설명
이미지 wordpress
Listening Port 80
EnvVar: WORDPRESS_DB_HOST DB address (db:3306)
EnvVar: WORDPRESS_DB_USER DB user (wp)
EnvVar: WORDPRESS_DB_PASSWORD DB password (wp)
EnvVar: WORDPRESS_DB_NAME DB name (wp)

Wordpress 컨테이너

설정 설명
이미지 mysql:5.7
Listening Port 3306
EnvVar: MYSQL_ROOT_PASSWORD DB root password (db:3306)
EnvVar: MYSQL_DATABASE DB database (wp)
EnvVar: MYSQL_USER DB user (wp)
EnvVar: MYSQL_PASSWORD DB password (wp)
DB data save directory /var/lib/mysql

이렇게 docker-compose.yml을 만들어 봅시다.

version: '3.9'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

  wordpress:
    image: wordpress:latest
    ports:
      - "60000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_USER: example username
      WORDPRESS_DB_PASWORD: example password
      WORDPRESS_DB_NAME: wordpress

volumes:
  db_data: {}

docker-compose 명령어

docker-compose pull [서비스]

: 필요한 이미지 다운

docker-compose build [서비스]

: 필요한 이미지 빌드

docker-compose up [서비스]

: 서비스를 구동. 서비스/네트워크가 없다면 만들고, 이미지가 없으면 빌드

: --build : 강제로 이미지 다시 빌드

: --force-recreate : 컨테이너 재생성

: -d : 데몬 모드로 실행

docker-compose ps

: 실행중인 서비스 목록 확인

docker-compose logs [서비스]

: -f : 로그 계속 보기

docker-compose stop [서비스]

: 서비스 멈춤

docker-compose start [서비스]

: 멈춰있는 서비스 컨테이너 실행

docker-compose run {서비스} {명령}

: 해당 서비스에 컨테이너 하나 더 실행

: -e : 환경변수

: -p : 포트

: --rm : 종료 시 자동 삭제

docker-compose exec {컨테이너} {명령}

해당 서비스의 컨테이너에서 명령어 실행