Inception

hhkim·2022년 8월 22일
1

42cursus

목록 보기
20/20
post-thumbnail

개념

가상 머신 vs 도커

도커 : Docker 와 VM의 차이

가상 머신(Virtual Machine)

하나의 서버를 여러 서버로 전환하는 물리적인 하드웨어의 추상화

  • 물리적인 하드웨어를 논리적으로 분할하여 독립적인 가상 환경을 만들어 놓은 것
  • 하이퍼바이저(예: VirtualBox)를 통해 하나의 호스트 OS에서 여러 개의 OS를 사용하는 방법
    👉 각 가상 머신이 OS, 애플리케이션, 필요한 바이너리와 라이브러리 전체를 포함하기 때문에 상대적으로 무겁고 느림
  • 다른 게스트 OS와 분리되어 독립된 공간과 자원을 할당 받음
    👉 보안성 굿

도커(Docker)

컨테이너 기반의 오픈소스 가상화 플랫폼

  • 컨테이너: 코드와 종속성을 함께 패키징하는 애플리케이션 계층의 추상화
    프로세스 단위의 분리 독립된 환경
  • 하나의 호스트 OS 위에 도커를 설치하고 그 위에 각 애플리케이션 환경을 설치 및 운영
    👉 애플리케이션이 각각 OS를 가지지 않기 때문에 메모리 공간을 적게 차지
  • 도커가 설치된 환경이라면 이미지를 통해 어디서든 동일한 환경 구축 가능
  • 도커 자체가 가상 머신이기 때문에 하이퍼바이저와 게스트 OS를 포함하고 있다고 함

도커 이미지와 도커 컨테이너

도커 이미지(Docker Image)

도커 컨테이너를 생성하는데 사용되는 애플리케이션의 파일들과 설정을 모아둔 것

  • 특정 프로세스를 실행하기 위해 필요한 모든 파일과 설정값(환경)을 지닌 것
    더이상의 의존성이 필요없음
  • VM의 ISO와 비슷한 역할이지만 더 가벼움
  • 상태값을 가지지 않으며 불변(immutable)
  • 이미지만 있으면 도커가 있는 환경에서 컨테이너를 생성 가능
  • DockerHub를 통해 버전 관리 및 배포 가능
  • Dockerfile이라는 파일로 이미지를 만듦
    이미지 생성 과정을 확인할 수 있고 수정도 쉬움
  • 여러 개의 읽기 전용 레이어로 구성되며, 파일이 추가되면 새로운 레이어 생성
    👉 도커는 여러 개의 레이어를 묶어서 하나의 파일 시스템으로 사용할 수 있게 함
  • 기반 이미지(base image): 부모가 없는 이미지 (예: OS들 - ubuntu, alpine, debian)
    자식 이미지(child image): 기반 이미지에 추가적인 기능을 더해 만든 이미지

도커 컨테이너(Docker Container)

실행중인 이미지의 인스턴스
애플리케이션의 종속성과 함께 프로그램 자체를 캡슐화하여 호스트 OS와 격리된 공간에서 프로세스를 동작시키는 기술

  • 종료되어도 메모리에서 삭제되지 않아서 다시 시작 가능
    👉 필요하면 명시적으로 삭제해야 함
    컨테이너를 삭제하면 컨테이너에서 생성한 파일이 사라짐
  • 컨테이너끼리 커널 공간과 호스트의 OS 자원을 고유

데몬(Daemon)

데몬 프로세스에 대한 이해😈
백그라운드에서 실행되면서 여러 작업을 처리하는 프로그램

  • 일반적으로 이름 끝에 d를 붙임
  • 보통 부모 프로세스를 갖지 않기 때문에 PPID가 1
  • 시스템을 시작할 때 데몬을 시작하는 경우가 많음
  • 네트워크 요청, 하드웨어 동작 등의 기능
    예) devfsd(하드웨어 설정), cron(주기적인 작업 실행)
  • 터미널을 가지지 않음
    👉 터미널이 종료되거나 세션이 끊겨도 시스템이 종료되기 까지는 유지됨

도커 데몬과 도커 클라이언트

  • 도커 데몬(Docker Daemon): 호스트의 백그라운드에서 실행되며, 도커 컨테이너의 빌드, 실행, 배포를 관리하는 서비스
  • 도커 클라이언트(Docker Client): 사용자가 도커 데몬과 상호작용할 수 있도록 하는 명령행 도구

도커가 명령어를 실행하는 원리

$ docker run alpine ls -l
total 48
drwxr-xr-x    2 root     root          4096 Mar  2 16:20 bin
drwxr-xr-x    5 root     root           360 Mar 18 09:47 dev
drwxr-xr-x   13 root     root          4096 Mar 18 09:47 etc
drwxr-xr-x    2 root     root          4096 Mar  2 16:20 home
drwxr-xr-x    5 root     root          4096 Mar  2 16:20 lib
......
......
  1. 도커 클라이언트가 도커 데몬에 신호
  2. 도커 데몬이 로컬에 이미지가 있는지 확인. 없으면 DockerHub에서 다운로드)
  3. 도커 데몬이 컨테이너를 생성하고 그 컨테이너 안에서 명령(위의 경우 ls -l) 실행
  4. 도커 데몬이 결과를 도커 클라이언트에 보냄

👉 가상 머신을 켜고 명령어를 실행하고 다시 종료하는 과정에 비하면 엄청 빠르다!

도커 볼륨(Docker Volume)

컨테이너에서 발생한 데이터들을 저장할 외부 공간

  • 호스트의 경로에 연결하여 컨테이너가 상태를 갖지 않도록 함(스테이트리스, stateless)
  • 컨테이너가 삭제되면 데이터도 사라지기 때문에 데이터를 보존하기 위해 사용
  • 실행 중인 컨테이너끼리 데이터를 공유해야 하는 경우에 사용

Dockerfile

Docker - Dockerfile 작성 / Build (이미지 제작)
Image-building best practices
도커 데몬이 이미지를 생성할 때 호출하는 명령어 목록을 담은 텍스트 파일

  • 베이스 이미지, 프로젝트 코드 위치, 의존성, 시작할 때 필요한 명령어 등을 포함
  • 명령어를 작성할 때 리눅스 명령어를 쓰면 돼서 간편
  • 레이어가 스택처럼 쌓이므로 변경이 빈번한 작업은 나중에 작성하는 것이 좋음

문법

  • FROM 베이스 이미지
  • RUN 빌드 타임에 실행할 명령어
  • ENV 환경변수
  • WORKDIR 작업을 실행할 경로
    • 지정한 경로가 없으면 생성
  • COPY 복사할 파일과 복사할 경로
  • VOLUME 컨테이너에 마운트할 볼륨 경로
  • CMD 컨테이너를 실행하기 위해 필요한 명령어
  • ENTRYPOINT docker run 명령을 실행할 때 같이 인자로 전달되는 명령어 (컨테이너 자체를 executable로 사용할 때 필요)

도커 컴포즈(Docker Compose)

도커 컴포즈 기초 및 문법
Docker Compose와 버전별 특징
여러 개의 컨테이너를 하나로 묶어주는 도구

  • YAML 파일에 서비스를 정의하면 명령어 하나로 모든 서비스를 생성하고 실행할 수 있음
    • 자동으로 서비스(애플리케이션 스택)들 사이에 네트워크 생성
  • 애플리케이션의 생명주기를 관리하는 명령어들이 있음
    • 시작, 중지, 재시작, 상태 확인, 로그 확인, 개별 서비스에 대한 명령어 실행
  • 하나의 호스트에 여러 개의 독립된 환경을 구성할 수 있음
  • 컨테이너가 생성되면 이전 컨테이너의 볼륨 데이터를 복사해서 데이터가 보존됨
  • 변경된 경우에만 컨테이너를 재생성
    👉 변경이 없으면 서비스가 재시작될 때 이미 있던 컨테이너를 재활용하므로 빠름
  • 변수를 설정해서 여러 환경에 맞게 커스터마이징할 수 있음
  • 여러 컴포즈 파일을 extends 키워드로 연결할 수 있음
  1. 어디서든 서비스가 생성될 수 있도록 애플리케이션의 환경을 Dockerfile에 정의
  2. 애플리케이션을 구성할 서비스들을 docker-compose.yml 파일에 정의
  3. docker-compose up으로 실행

문법(Version 3)

  • version 스키마 버전
    • 최신 버전을 쓰는 것을 권장
    • 버전 3 이후에는 버전을 쓰지 않는 것 같은데 잘 모르겠다 (참고)
      예시 튜토리얼 같은 곳에서는 버전 3.9를 명시하고 있음
  • services: 애플리케이션을 구성할 서비스 목록 (컨테이너를 실행할 때 필요한 정보 명시)
    • 서비스 이름 (아래의 목록은 순서가 상관없음)
      • build 빌드할 Dockerfile의 경로
      • image 사용할 이미지
      • command 컨테이너에서 수행할 명령어
      • ports 포트 정의
      • working_dir 작업할 경로
      • container_name 컨테이너 이름
      • volumes 마운트할 볼륨 (상대 경로 사용 가능)
      • environment 환경변수
      • networks 사용할 네트워크 정의
  • volumes: 미리 생성해두고 컨테이너에서 불러와서 사용할 볼륨
    • 볼륨 이름 (볼륨 이름만 명시하면 기본 옵션을 사용)
    • driver
    • driver_opts 드라이버 옵션 설정, 리눅스의 mount 실행과 동일 (참고)
  • networks: 컨테이너 간 네트워크 설정
    • 네트워크 이름

CGI와 fastCGI

What is Common Gateway Interface (CGI)?
CGI와 FastCGI 알아보기
CGI, FastCGI, PHP-FPM 개념
Common Gateway Interface (공용 게이트웨이 인터페이스)

  • 웹서버와 외부 프로그램 사이에 정보를 주고받는 방법이나 규약
  • 클라이언트(브라우저)가 서버에 보낸 요청이 정적인 HTML이 아니라 동적인 PHP 등이라면 서버는 CGI를 요청하고 CGI를 사용하는 CGI 프로그램이 CGI 응답을 보내면 서버는 이걸 HTTP 응답으로 바꿔서 클라이언트로 다시 보냄
  • 표준 입출력을 이용하므로 대부분의 프로그래밍 언어로 구현 가능
  • CGI는 요청이 올 때마다 새 프로세스를 생성하는데, fastCGI는 이전에 생성한 프로세스를 재활용해서 성능 개선
    (php-fpm은 CGI 프로그램!)

구현

VirtualBox 세팅

중간중간 스냅샷 찍어서 백업해두기! (참고)

  1. VirtualBox에 Ubuntu 설치: 메모리는 4기가, 파일 크기는 10기가
  1. 패키지 설치
    su -
    apt-get update
    apt-get install -y curl
    apt-get install -y git
    apt-get install -y vim
    apt-get install -y nscd
  2. Docker 설치 (문제있을 때 참고)
  3. docker-compose 설치

공유폴더 설정

mount -t vboxsf (공유 폴더 이름) /mnt/share

virtualBox에서 실행하니까 나는 오류들...

nginx

MariaDB

WordPress

php-fpm
nginx, php-fpm간 통신

error establishing a database connection

이것 때문에 며칠을 고생했는데 mariadb가 제대로 실행되기 전에 워드프레스가 연결을 시도하면서 그런 거였다. Dockerfile에서 wp core install 명령을 바로 실행하지 않고 따로 쉘 스크립트를 작성한 뒤 컨테이너가 만들어진 후 CMD로 실행하니까 해결됐다.

networks

  • docker-compose.yml에 네트워크를 정의하면 도커 컴포즈 실행 시에 자동으로 네트워크 설정
  • docker-compose run [서비스명] ping [서비스명]으로 ping 날려서 연결이 잘 됐는지 확인
    예) docker-compose run nginx ping mariadb

사용자 정의 네트워크를 사용해야 하는 이유

기본적으로 default 네트워크가 생성되고 bridge 방식으로 연결되긴 함

  • default 네트워크에서는 IP 주소로만 서로에게 접근이 가능하기 때문에 이름을 사용하려면 따로 네트워크를 정의
    (아니면 --link 옵션을 써야 하는데 섭젝에서 금지하기도 했고 레거시)
  • 컨테이너가 추가되면 --network 옵션을 쓰지 않는 이상 기본적으로 default 네트워크에 속하게 되는데, 이는 예기치 않은 문제를 일으킬 수 있으므로 사용자 지정 네트워크를 만드는 것이 안전
  • default 네트워크 설정을 변경하면 호스트의 iptables 자체가 변경되어야 하기 때문에 도커를 재시작해야 하므로 비효율적
  • --link 옵션 없이 도커 볼륨, 도커 컴포즈 변수 등을 통해 환경 변수 공유 가능

volumes

Makefile

최적화

  • Best practices for writing Dockerfiles
    • RUN, COPY, ADD만 레이어를 생성함
    • 레이어 수 줄이기: 여러 줄의 RUN을 한 줄로
    • COPYADD는 파일의 변경사항까지 비교해서 캐싱하기 때문에 여러 줄로 분리해서 작성
    • 레이어는 스택으로 쌓이기 때문에 변경이 빈번한 레이어를 나중에 작성 (이전 레이어는 캐시에 저장된 것을 사용하도록)
    • 설치하는 패키지는 알파벳 순서로 줄을 분리해서 쓰면 관리가 용이

명령어 정리

docker

# 이미지 목록 확인
docker images

# 컨테이너 생성 및 실행
docker run [이미지 이름]		# 이미지를 가지고 컨테이너를 생성/실행
# 옵션
-it [이미지 이름]				# 인터랙티브 쉘(interactive tty) 실행
-d							# detached 모드로 실행 (현재 터미널에서 분리하여 실행)
--name [컨테이너 이름]			# 컨테이너 이름 설정
-e [환경변수명]="[값]"			# 컨테이너 환경변수 설정
-P							# 컨테이너의 모든 포트를 호스트의 랜덤한 포트로 연결
-p [호스트포트]:[컨테이너포트]	# 포트를 명시적으로 매핑

# 컨테이너 목록 확인
docker ps		# 현재 실행중인 컨테이너 목록 확인
# 옵션
-a	# 현재 실행중 + 실행됐던 컨테이너 목록 확인

# 컨테이너 콘솔 로그 확인
docker logs [컨테이너 id/이름]

# 실행중인 컨테이너 내부에서 명령 실행
docker exec [컨테이너 id/이름] [명령어]

# 컨테이너 실행 중단
docker stop [컨테이너 id/이름]

# 컨테이너 삭제
docker rm [컨테이너 id/이름]
# 옵션
-f	# 실행중인 컨테이너 강제 삭제

# 컨테이너 포트 확인
docker port [컨테이너 id/이름]

# 이미지 빌드
docker build [경로]
# 옵션
-t [이미지 이름]	# 이미지 이름 지정. [이미지 이름]:[태그 이름]을 통해 태그를 지정할 수도 있음

docker-compose

# 도커 컴포즈 실행
docker-compose up	# 현재 디렉토리의 docker-compose.yml 파일을 참고하여 실행
# 옵션
-d		# detached 모드 (백그라운드에서 실행)
--build	# build하고 실행

# 도커 컴포즈 실행 종료
docker-compose down
# 옵션
--volumes	# 데이터 볼륨까지 삭제

# 실행 중인 서비스 목록
docker-compose ps

# 로그 확인
docker-compose logs	# 뒤에 특정 서비스명을 써서 해당 로그만 골라서 볼 수도 있음
# 옵션
-f	# follows (실시간 출력 확인)

# 특정 서비스에서 명령어 실행
docker-compose run [서비스 이름] [명령어]

# 서비스 실행 중단
docker-compose stop

mariaDB

# 데이터베이스 목록 확인
show databases;

# 데이터베이스 선택
use [데이터베이스 이름];

# 테이블 목록 확인
show tables;

# 사용자 목록 확인
select * from mysql.user;

참고

도커 한방에 정리 🐳 (모든 개발자들이 배워보고 싶어 하는 툴!) + 실습
Docker for Beginners
Get started with Docker Compose
Use Docker Compose
How To Install WordPress With Docker Compose

0개의 댓글