기술

Docker 관련 개념 정리

NONAME DIALOG 2024. 10. 25. 14:57

도커가 뭘까

Docker

  • Docker는 애플리케이션 구축, 구현 및 테스트를 위해 격리된 가상화 환경을 생성하는 서비스형 플랫폼이다.
  • Docker는 컨테이너 엔진으로 리눅스 커널 기능을 사용하여 운영 체제 위에 컨테이너를 만들고,Docker 자체는 서비스의 컨테이너를 관리하는 데몬으로 실행된다.
  • Linux 커널의 도커 엔진
    • namespace: 프로세스를 독립시켜주는 가상화 기술이다. 각 컨테이너에서 실행된 프로세스가 시스템(user, 파일, 네트워크, 호스트명, 프로세스)등에 대해 독립할 수 있게 해준다.
    • cgroups: 자원(CPU, 메모리, network bandwidth)에 대한 제어를 가능하게 해주는 리눅스 커널의 기능이다.Docker는 컨테이너라는 가상의 '격리 환경'을 만들기 위해 리눅스의 namespace과 cgroup이라는 기능을 사용한다. (namespace와 cgroup으로 만들어진 컨테이너를 LXC라고 부른다)

Docker image

  • 파일로 어필리케이션 실행에 필요한 독립적인 환경을 포함
  • Aplication을 포장 및 전송하기 위해서 사용
  • 소스 코드, 라이브러리, 종속성, 도구 및 응용 프로그램을 실행하는데 필요한 기타 파일을 포함하는 불변파일
  • 도커 컨테이너 == 실행 중인 이미지
  • 컨테이너는 수정가능하지만 이미지는 수정 불가능함
  • 컨테이너 실행에 필요한 파일과 설정 값 등을 포함하고 있는 것. (상태값을 가지지 않고 변하지 않음, Immutable)

Docker Container

  • 가상화된 런타임 환경
  • 응용프로그램을 빠르고 쉽게 시작할 수 있는 portable units 이다
  • 이미지를 실행한 상태로 볼 수 있고, 변하는 값은 컨테이너에 저장됨.

Docker Volume

  • Docker volume이란 디렉토리를 매핑하는 것입니다.
  • 즉, Docker host의 디렉토리와, container의 디렉토리를 연결하는 것입니다.
  • 도커에서 데이터 영속성을 보장하기 위한 방법 중 하나!

Docker Images VS Container

  • 컨테이너가 존재하려면 이미지를 실행해야하지만, 이미지는 컨테이너 없이 존재할 수 있다.
  • 도커 컨테이너는 실행 중인 이미지 인스턴스로 간주함
Dockerfile --(Build)--> Image --(Create)--> Container

출처:

https://sunrise-min.tistory.com/entry/Docker-Container와-Image란-무엇인가

https://velog.io/@geunwoobaek/컨테이너-및-도커-개념정리

VM vs Docker

virtual machine

: 자원을 똑 떼어내서 가상 환경에 할당해주기 때문에 쓸 수 있는 자원에 한계가 많음. 그리고 각자 독립된 os를 가지고 있기 때문에 무거움

docker

: host자원을 공유하기 때문에 컨테이너가 필요한 만큼 자원을 끌어다 쓸 수 있고 os를 host와 공유하고 있기 때문에 가벼움

VM은 docker에 비해 메모리나 자원에 관해서 처음부터 정해놓고 실행하기에 비효율적이고 확장성이 떨어진다

Docker의 작동방식

도커는 이미지를 통째로 생성하지 않고, 바뀐 부분만 생성한 뒤 부모 이미지를 계속 참조하는 방식으로 동작하는데, 이것을 레이어라고 한다

출처:

https://avengersrhydon1121.tistory.com/287


Dockerfile 작성법

Dockerfile

  • docker에서 이미지를 생성하기 위한 용도로 작성하는 파일 (이미지 정보를 적어둔 템플릿과 유사함)
  • 흔히 cd 이미지를 떠올려보면 쉽게 이해할 수 있다고 생각한다. 컨테이너는 이미지를 바탕으로 만든다고 생각하면 된다.

Dockerfile cmd

  1. FROM베이스 이미지 : 어느 정도 기본적이 구성요소들이 갖추어진 상태의 이미지
  2. 도커파일에서 베이스 이미지를 지정하는 지시어
  3. RUN명령어가 실행된 후의 변경사항이 새 이미지에 반영된다.
  4. command를 실행하여 새 이미지에 포함시키는 역할
  5. CMDRUN과의 차이 :
    • RUN은 이미지를 빌드할 때 실행
    • CMD는 이미 만들어진(빌드 완료된)이미지로부터 도커 컨테이너를 시작할 때 실행
    • (컨테이너가 실행되었을 때 명령이 실행됨)
  6. 컨테이너가 시작될 때 실행할 커맨드를 지정하는 지시어
  7. ENTRYPOINTCMD와 달리 컨테이너 실행 시 param값을 대체할 수 없다
  8. FROM ubuntu ENTRYPOINT ["/bin/echo", "Hello"] CMD ["world"] $ docker run -it --rm --name test Hello world $ docker run -it --rm --name test toramko Hello toramko => CMD의 param인 'world'가 대체된다
  9. 컨테이너가 시작 시 실행될 command를 지정
  10. COPY
  11. Host 내에 있는 파일 또는 디렉토리를 컨테이너의 파일시스템으로 복사
  12. WORKDIR
  13. 작업 디렉토리를 설정한다
  14. ADD단순히 로컬 파일 또는 디렉토리를 Docker 이미지로 복사하려는 경우에는 COPY를 사용하는 것이 적절하다.
  15. COPY와 같이 복사하는 것이지만 복사하려는 대상파일이 압축파일인 경우 파일의 압축을 해제하여 복사함
#FROM : Docker Base Image (기반이 되는 이미지, <이미지 이름>:<태그> 형식으로 설정)
	FROM debian:bullseye
#WORKDIR : "RUN", "CMD", "ENTRYPOINT" 명령이 실행될 작업 디렉터리
	WORKDIR /etc/mysql
#COPY : 파일 복사
	COPY ./tools/entrypoint.sh /entrypoint.sh
#RUN : Shell Script 또는 명령을 실행
	RUN chmod +x /entrypoint.sh
#ENTRYPOINT : 컨테이너가 시작되었을 때 스크립트 실행
	ENTRYPOINT ["/entrypoint.sh"]
#CMD : 컨테이너가 실행되었을 때 명령이 실행
	CMD ["mysqld"]

Docker-Compose 란

Docker-Compose

  • 여러 컨테이너를 가지는 애플리케이션을 통합적으로 만들고, 각각의 컨테이너를 시작 및 중지하는 작업을 더 쉽게 수행할 수 있도록 도와주는 도구
  • 여러대의 컨테이너(독립된 컴퓨터라고 생각하면 됨)를 적절하게 연결하고 관리하는 기술

Docker-Compose Command

  • 기본 명령중지 : docker-compose stop
  • 실행하면서 빌드(서비스 시작 전 이미지를 새로 만든다) : docker-compose up --build
  • 실행 : docker-compose up

Docker-Compose.yml 작성양식

  • build
    • 해당 서비스의 이미지를 빌드하기 위한 Dockerfile이 위치하는 경로를 저장한다.
  • ports
    • 호스트 OS와 컨테이너의 포트를 바인딩시켜준다.
    • 따옴표와 함께 문자열로 지정해야 한다.
    • 형식은 “host:container” 또는 “container”
    • 외부로 노출시킬 포트의 맵핑을 명시하는 부분
    • 바인드(bind)가 필요한 호스트 외부 포트와 컨테이너 내부 포트를 지정
  • image
    • docker-compose 안에서 베이스 이미지를 지정한다.
  • command
    • 해당 서비스가 올라올 때 Dockerfile의 CMD 명령문을 무시하고 실행할 명령어를 설정한다.
  • depends_on
    • 서비스 간의 종속성 순서대로 서비스를 시작한다.
    • A: depends_on: -B A 애플리케이션이 올라오기 전에 B가 먼저 올라와야 한다.
  • environment
    • 컨테이너의 환경 변수를 지정한다.

dumb-init

PID1

https://swalloow.github.io/container-tini-dumb-init/

 

  • VM 대신에 Docker를 이용하는 이유 중 하나..
  • PID 1으로 등록된 단 하나의 프로세스만을 Container가 담당하겠다는 의미, 단 하나의 Container가 곧 단 하나의 서비스 (프로세스)를 의미하여 서버의 환경 관리 측면에서 일관성을 갖게 한다.
    • 이와 같은 측면에서 임의의 Loop과 tail -F, bash와 같은 행위가 금지됨
    • ⇒ Container의 실행이 곧 서비스의 실행으로 이어지지 않는 행위
     

  • 대다수의 OS에서 첫번째 Process ID 즉, PID 1은 초기에 실행되는 init process가 할당 받는다. init은 고아프로세스를 입양하기 때문에 모든 프로세스의 직/간접적인 부모 프로세스가 된다.
  • 컨테이너에선 init 프로세스가 없기 때문에 가장 먼저 실행된 일반 애플리케이션이 PID 1을 할당 받게 된다. 이 경우 크게 두 가지가 문제가 된다.
    • 첫째로 정상적인 시그널 처리를 하지 못할 수 있다. ⇒ 일반 애플리케이션은 다른 프로세스를 관리할 목적으로 실행된 것이 아니기 때문에 적절한 시그널 핸들러를 가지고 있지 않을 가능성이 크기 때문이다.
    • 둘째로 고아프로세스를 처리할 수 없어진다. ⇒ 고아프로세스는 PID1을 새로운 부모 프로세스로 취급하게 되며 PID1이 고아프로세스의 종료상태를 회수하며 좀비 프로세스가 되는 것을 방지한다. 하지만 이러한 역할을 하지 못하는 일반 애플리케이션의 경우 이러한 문제를 막을 수 없다.

dumb-init

  • dumb-init은 이러한 문제를 해결하고 컨테이너를 일반 프로세스와 같은 형태로 사용할 수 있도록 지원하기 위해 만들어짐
  • 아래와 같은 예시로 프로세스 트리를 만들었다
  • - docker run (on the host machine) - dumb-init (PID 1, inside container) - python my_server.py (PID 2, inside container)
  • dumb-init은 모든 signal에 대해 signal handler를 등록하고 해당 signal을 프로세스 세션으로 전달합니다. 파이썬 프로세스는 더 이상 PID 1로 실행되지 않기 때문에 dumb-init이 TERM과 같은 신호를 전달할 때 handler를 등록하지 않아도 프로세스 종료가 가능합니다.
  • dumb-init은 signal propagation 뿐만 아니라 고아 상태가 된 자식 프로세스를 거두는 역할도 수행합니다.

Tini

Tini는 컨테이너에 사용할 수 있는 작고 간단한 init입니다. 이는 단일 자식을 생성하고 신호 전달을 수행할 뿐만 아니라 좀비 프로세스를 수확하는 동안 자식이 종료될 때까지 기다리는 방식으로 작동합니다.

docker-compose.yml에서 service부분에 init:true를 통해 생성이 가능하다
init: true 옵션을 사용하면 Docker 컨테이너가 시작될 때 tini라는 초기화 프로세스가 실행됩니다. 
이 옵션은 컨테이너 내에서 프로세스를 정상적으로 종료하고 신호를 처리하는 데 도움이 됩니다. 

특히, tini는 좀 더 신속하게 종료 시그널을 처리하고 좀 더 안정적으로 컨테이너를 종료하는 데 도움이 됩니다.

NGINX

NGINX란?

  • 가볍고 높은 성능을 가진 Web Server
  • HTTP Server로 활용되며 정적 파일들을 처리하기 위해 사용
  • Reverse Proxy Server로 활용됨
  • 80번 포트로 들어오는 내용을 3000, 4000, 9000 등의 다른 포트로 분산 시켜줌

nginx directives

  • simple directive : 이름과 값이 있고 세미콜론으로 끝난다.
  • worker_process 1;
  • block directive : 블럭을 통해서 여러 directive 를 감싼 형태로 정의된다.
  • http { server { location / { root /path/to/html; } location /images/ { root /path/to/image; } } }

nginx.conf 구문 구조

  • http
    • http 블록은 HTTP 통신과 관련된 모듈의 지시어 블럭을 정의하는 블럭이다.
    • http, server, location 블럭은 계층구조를 가지고 있어서 http 블럭안에 server 와 location 블럭이 위치할 수 있다.
    • 계층구조에 따라서 상위 블럭에서 정의한 지시어는 하위 블럭에 값이 상속된다.
    • 예를들어 http 블럭에서 정의한 값은 server 블럭의 기본값이 되고 server 블럭에서 정의한 값을 location 블럭의 기본값이 된다.
    • 만약 하위 블럭에서 해당 설정을 새로 정의하면 상위 지시어는 무시되고 새로 정의된 값으로 설정된다. http 블럭 안에 한 개 이상의 server 블럭을 선언할 수 있다.
  • server
    • 하나의 호스트를 선언하는데 사용하는 블럭으로 http 블럭 안에서만 사용할 수 있다. server 블럭에는 한 개 이상의 location 블럭을 선언할 수 있다.
      • location : location 블럭은 server 블럭 안에 정의되고, 특정 url 을 처리하는 방법을 정의한다.
        • 처음 요청이 들어왔을 때 보여줄 페이지들이 속해있는 경로와 초기 페이지인 index 지정
        • url로 접속했을 경우 index.html, index.htm으로 정의된 파일들을 보여줌
      • listen
        • 해당 포트로 들어오는 요청을 해당 server {} 블록의 내용에 맞게 처리하겠다는 뜻
      • server_name
        • 호스트 이름 지정
        • 가상 호스트가 있는 경우 해당 호스트명을 넣으면 되고, 로컬에서 작업하고 있는 내용을 nginx를 통해 띄우려고 하는 경우에는 localhost라고 적으면 됨
      • error_page
        • 요청 결과의 http 상태코드가 지정된 http 상태코드와 일치할 경우 해당 url로 이동
        • 보통 403, 404, 502 등의 에러처리를 위해 사용
  • events
    • events 블럭은 네트워크의 작동 환경을 설정하는 블럭이다.
    • events 블럭의 지시어는 events 블럭 내부에서만 사용할 수 있고, http, server, local 블럭과는 상속 관계를 가지지 않는다.
      • worker_connections# worker_processes * worker_connections 를 계산한 값이 nginx 서버의 최대 접속자 수이다.
      • # worker process 가 동시에 처리할 수 있는 접속자 수를 정의한다.

출처 : https://jammdev.tistory.com/217

WordPress

Wordpress는 PHP를 기반으로 한 설치형 블로그이다.

PHP와 HTML 코드 편집 없이도 다시 정리할 수 있는 위젯이 포함되어 있고, 테마도 설치해 자유롭게 전환할 수 있다. 테마 안의 PHP와 HTML 코드는 좀 더 세분화된 맞춤 페이지를 위해 편집할 수 있다.

WP-CLI

wp-cli는 Wordpress의 커맨드라인 인터페이스이다. 웹브라우저 없이 CLI 환경에서 Wordpress를 설정할 수 있게 해준다. 컨테이너 이미지를 설계할 때 유용하다.

WP-CLI는 PHAR로 작성된 유틸리티로써 명령어로 Wordpress 를 관리할 수 있는 유틸리티이다.

플러그인 관리, 워드프레스 업그레이드등의 관리 작업을 커맨드로 실행할 수 있으므로 자동화된 관리가 가능하며 다수의 워드프레스 사이트를 손쉽게 운영할 수 있는 장점이 있다.

PHP

PHP(PHP: Hypertext Preprocessor)는 C언어를 기반으로 만들어진 서버 측에서 실행되는 서버 사이드 스크립트 언어입니다.

PHP는 동적 웹 페이지를 쉽고 빠르게 만들 수 있도록 해주는 데 그 목적이 있습니다.

PHP로 작성된 코드를 HTML 코드 안에 추가하면, 웹 서버는 해당 PHP 코드를 해석하여 동적 웹 페이지를 생성합니다. 출처 : https://tcpschool.com/php/php_intro_intro

CGI & Fast CGI

CGI는 Common Gateway Interface의 약자로 웹서버와 외부 프로그램을 연결해주는 표준화된 프로토콜이다. 웹서버로 요청이 들어왔을 때 그것이 웹서버가 처리 할 수 없는 정보일 때 그 정보를 처리 할 수 있는 외부 프로그램을 호출해서 외부 프로그램이 처리한 결과를 웹서버가 받아서 브라우저로 전송하는 것이다. 외부 프로그램은 C, C++PerlPHPPython 등 어떤 언어로든 작성될 수 있는데, 이것이 가능한 것은 웹서버와 외부 프로그램 사이에 통용되는 공통의 규칙이 정의되어 있기 때문이다.

Apache, Nginx 등의 웹 서버를 쓰고 PHP 프로그래밍이나 Python 프로그래밍 등의 여러가지 언어를 쓰는데 이것들이 문제 없이 사용할 수 있는 것은 그 사이에 CGI라는 표준이 있기 때문이다.

속도를 개선한 것이 FastCGI다. FastCGI는 여러 개의 request가 들어와도 이미 만들어져있는 process를 공유해서 처리하기 때문에 process를 생성하고 삭제하는데 소요되는 리소스, 시간 등이 절약된다.

PHP-FPM는 PHP FastCGI Process Manager의 약자로 PHP를 FastCGI 모드로 동작하게 해준다. 하나의 process로 여러 개의 request들을 처리해주는 manager인 것이다.

네트워크 연결방법

Docker Network

Docker Network란 같은 호스트 내에서 실행중인 컨테이너 간 연결할 수 있도록 돕는 논리적 네트워크 개념이다.

  • Docker 컨테이너끼리 통신할 때는 Docker 네트워크를 통해 수행
  • Docker는 기본 네트워크 값으로 bridge, hosts, none 세 개의 네트워크를 만듦
    • bridge : 네트워크는 하나의 호스트 컴퓨터 내에서 여러 컨테이너들이 서로 소통할 수 있도록 해줍니다.
    • host : 네트워크는 컨테이너를 호스트 컴퓨터와 동일한 네트워크에서 컨테이너를 가동하기 위해서 사용됩니다.
    • none : 네트워크는 네트워크를 사용하지 않는 것입니다.
     

Docker Compose Network

docker-compose network의 driver도 docker network와 동일하다.

docker-compose에 있는 컨테이너들은 기본적으로 ". yml파일이 있는 디렉토리명_default"로 동일한 네트워크를 가지게 된다.

compose는 우선적으로 네트워크를 먼저 생성하고 container를 구동시킨 후 네트워크에 연결해준다.

docker-compose down를 할 때에도 마찬가지로 종료, 제거한 후 네트워크를 제거한다.

출처 : https://velog.io/@hyeseong-dev/docker-docker-container-네트워크

https://developer-eun-diary.tistory.com/145


SSL/TLS

  • 보안 소켓 계층(Secure Sockets Layer, SSL) 인증서는 브라우저(사용자의 컴퓨터)와 서버(웹사이트) 사이의 암호화된 연결을 수립하는 데 사용됩니다.
  • 전송 계층 보안(Transport Layer Security, TLS)은 SSL의 향상된, 더욱 안전한 버전입니다. SSL이 더욱 일반적인 용어이기 때문에 DigiCert는 보안 인증서를 여전히 SSL로 언급하지만 DigiCert에서 SSL을 구입하면 가장 신뢰할 수 있는 최신 TLS 인증서를 얻을 수 있습니다.
  • 암호화된 통신을 하는 프로토콜인 HTTPS를 서버에서 구현하기 위해서 위 기업이 발급한 인증서가 필요한데 이런 발급 기관을 **CA(Certificate Authority)**라고 한다.
  • self-signed SSL 인증서는 자체적으로 발급받은 인증서이며, 로그인 및 기타 개인 계정 인증 정보를 암호화한다. self-signed SSL 인증서를 만드는 방법 중 하나는 무료 오픈소스인 openssl을 이용해 만드는 것이다. HTTPS를 위해 필요한 인증서파일(.crt)을 openssl이 발급해준다.
  • TLS란
    • 인터넷에서의 정보를 암호화해서 송수신하는 프로토콜
  • TLS v1.2/v1.3 특징
    • Handshake 과정에서 필요한 서로간의 통신 횟수가 TLS 1.3버전에서 줄어들면서 키 교환에 따른 필요 시간이 단축 됨
  • SSL/TLS
    • SSL : 암호화 기반 인터넷 보안 프로토콜이다.
    • TLS : SSL의 업데이트 버전

HTTP/HTTPS

  • HTTP
    • HTTP(Hypertext Transfer Protocol)는 클라이언트와 서버 간 통신을 위한 통신 규칙 세트 또는 프로토콜
    • 사용자가 웹 사이트를 방문하면 사용자 브라우저가 웹 서버에 HTTP 요청을 전송하고 웹 서버는 HTTP 응답으로 응답
    • 웹 서버와 사용자 브라우저는 데이터를 일반 텍스트로 교환
  • HTTPS
    • HTTP의 확장 버전 또는 더 안전한 버전
    • HTTPS에서는 브라우저와 서버가 데이터를 전송하기 전에 안전하고 암호화된 연결을 설정
  • 80
    • HTTP가 문서화되기 이전부터 보통 사용하지 않는 빈 포트 번호였다.
    • 1991년 HTTP 0.9 버전에서 처음으로 문서화되면서 기본 포트로 지정되었다.
  • 443
    • RFC 1700 이전까지는 빈 포트 번호였다.
    • Kipp E.B. Hickman의 요청으로 1994년 10월에 RFC 1700 문서에 443이 추가되었다.
    • 443인 이유는 빈 칸에 순서대로 배정하다 보니 그렇게 된 것 같다.