도커는 컨테이너 기반의 가상화 플랫폼이다.
컨테이너란
Linux 자체 기능만으로 구현하여 프로세스 단위로 독립적인 공간을 만드는 기술을 말한다.
기존의 가상머신인 VM은 Host OS위에 Guest OS를 따로 설치해서 독립된 공간을 만드는 방식이다. 그래서 크기도 크고 성능저하도 일어난다.
하지만 도커는 Guest OS없이 기존 OS에 내장되어 있는 내부 컨테이너를 사용하기 때문에 도커 엔진만 사용해서 독립된 공간을 만든다.
마이크로 서비스란
여러 모듈들을 여러 프로그램으로 나누어 구동하는 기술 방식이다.

(이미지 출처 - https://www.edureka.co/blog/what-is-docker-container)
도커의 이미지는 컨테이너를 만들기 위한 정보를 담고 있는 압축파일같은 존재이다.
이미지를 통해 컨테이너가 만들어지며, 한번 만들어진 이미지의 정보는 변하지 않는다.
다양한 API가 제공되어 자동화가 가능하다.
이미지는 여러가지 정보들을 가지고 있기 때문에 용량이 좀 있다.
기존에 있던 이미지와 중복되는 내용이 있는 새 이미지를 가져오게 되면, 같은 내용이 겹치는데도 새로 가져오게 되니까 용량은 더 커질 것이다. 그래서 도커는 해당 문제를 처리하기 위해 레이어라는 개념을 사용한다.
이미지는 여러 레이어 구조로 되어있다.
그리고 이미지들은 레이어들을 공유한다.
만약 여러 이미지에 같은 내용이 있다면 해당 이미지들은 겹치는 내용의 레이어들을 서로 공유하고 있을 것이다. 그래서 중복되는 내용이 있는 이미지를 새로 갖게 되더라도 용량이 크게 불어나지 않게되는 것이다.
컨테이너란 특정 어플리케이션이나 환경을 배포하기 위해 즉석에서 생성할 수 있는 표준화된 단위이다.
이미지를 사용해서 컨테이너를 생성할 수 있다.
생성된 컨테이너는 독립적인 공간에 이미지의 목적에 맞는 파일 시스템과 여러 자원및 가상화된 네트워크를 사용할 수 있게된다.
컨테이너에서 어떤 작업을 하더라도 머신과 다른 컨테이너에는 영향을 끼치지 않는다.
컨테이너에서 작업한 내용들은 컨테이너 레이어에 기록이 된다.
그리고 컨테이너가 삭제되면 해당 레이어도 삭제가 된다.
실수로 컨테이너를 날리게 된다면 해당 컨테이너에서 했던 내용들이 전부 날라가게 되어 어쩔떈 엄청난 사태로 이어질 수 도 있는 것이다.
그래서 해당 문제점을 해결하기 위해서, 그리고 여러 컨테이너끼리 저장 공간을 공유하고 데이터를 읽고 쓰기 위해 볼륨과 바인드 마운트, tmpfs 마운트(리눅스용, 임시 방법)라는 방법이 있다.

볼륨은 도커 컨테이너에서 데이터를 유지하기 위한 기본 메커니즘이다.
볼륨을 사용하면 호스트 시스템의 도커 스토리지 디렉토리내에 새 볼륨 디렉토리가 생성되고 도커가 직접 볼륨을 관리한다.
또한 볼륨을 사용한다고 해서 컨테이너의 크기가 늘어나지도 않고, 컨테이너 생명 주기 외부에 있기때문에 컨테이너를 지워도 데이터가 남아있다.
장점
볼륨으로 사용할 폴더를 설정할떄 설정할 경로폴더안에 데이터가 있다면 마운트할때 안에 있던 내용들이 다 사라진다고 하니 이 부분은 조심하면 좋을 것 같다.

성능은 매우 뛰어나지만 특정 디렉토리 구조를 사용할 수 있는 호스트 시스템의 파일을 의존하기 떄문에 볼륨에 비해 기능이 제한적이다.
바인드 마운트를 사용하면 호스트 시스템의 파일또는 디렉토리가 컨테이너에 마운트 된다. 그래서 도커가 관리할 수 없다.
도커 공식 문서에서도 바인드 마운트보단 볼륨을 사용하는 것을 권장한다.
여러 명령어들이 적혀있는 이미지 설정파일이다. 해당 파일을 작성후 build하면 이미지가 생성된다.
계속 컨테이너를 생성&삭제하기 때문에 명령어 줄은 적을 수록 좋다고 한다.
도커 클라이언트와 도커 데몬
도커는 클라이언트와 서버 두가지 구조로 나뉘어져 있다.
도커 클라이언트가 클라이언트 부분을 담당하여, API를 사용할 수 있도록 CLI를 제공한다.
도커 데몬은 서버 부분을 담당하며, 도커 프로세스가 실행되어 서버로서 입력을 받을 준비가 된 상태를 뜻한다.
사용자가 터미널에 Docker 명령어를 입력하면 도커 클라이언트는 /var/bin/docker.sock에 위치한 유닉스 소켓을 통해 도커 데몬을 호출해 명령어를 전달한다.
도커 데몬은 해당 명령어를 파싱하여 명령어 작업을 수행한다.
그리고 수행 결과를 도커 클라이언트에 반환하여 사용자에게 결과를 출력해 보여준다.
데몬 프로세스
그리고 데몬 프로세스는 사용자가 직접 제어하지 않고 백그라운드에서 여러 작업을 하는 백그라운드 프로세스를 뜻한다
데몬 프로세스는 PPID가 1이거나 다른 데몬 프로세스를 부모로 갖는다.
이러한 이유는 쉘이 종료되었을때 자식 프로세스들이 종료되는 현상을 방지하기 위해서이다.
데몬 프로세스는 대게 네트워크 요청, 하드웨어 동장, 여러 프로그램에 반응하는 기능을 담당하게 되고, 하드웨어 설정이나 주기적인 작업을 실행하기도 하며 다양한 목적으로 사용된다.
일반 프로세스는 명령이 끝나면 프로세스가 종료되지만 데몬 프로세스는 명령이 끝나도 사라지지 않아 계속해서 명령을 수행한다.
도커는 IP를 172.17.0.N (B클래스 사설 IP)를 사용하고 있으며, 차례대로 사용한다.
그리고 veth(Virtual Ethernet)로 시작하는 네트워크 인터페이스와 컨테이너 끼리의 통신을 하게해주는 브릿지 역할을 하는 docker0이라는 것이 있다.
veth는 도커 엔진에 의해서 생성되고 docker0은 도커 데몬에 의해 생성된다.
컨테이너는 기본적으로 veth와 docker0 브릿지로 되어있기때문에, 따로 설정을 해주지 않는이상 계속 해당 형태로 간다.
모든 veth 인터페이스는 docker0에 바인드 되어있다.
그래서 모든 veth를 관리하고 외부 네트워크와 통신할 수 있게끔 eth0을 연결해준다.
도커의 네트워크 방식에는 Bridge말고도 더 여러가지 방법이 있다.
도커 스웜이란
여러 컨테이너를 관리해주는 툴
FROM debian:buster
이미지를 만들기위해 사용할 기반 이미지를 설정하는 명령어이다. 필수로 작성해야한다.
RUN apt-get update
레이어를 생성하기 전에 컨테이너에서 해당 명령을 수행한다.
그리고 명령이 수행된 후 해당 상태의 레이어가 만들어진다.
명령어가 많이 수행될수록 레이어가 많아지므로 명령어를 최소화하는 것이 중요하다고 한다.
COPY ./my_file /root
Host에 있는 파일을 이미지내 해당 경로로 파일을 복사하는 명령어이다.
EXPOSE 9000
사용할 포트를 명시하는 명령어. 명시만 하고 실제로 해당 포트와 바인딩 되는 것은 아니다.
포트를 바인딩하기 위해서는 직접 바인딩해야한다~
두 명령어 다 도커파일을 사용하여 만들어진 이미지를 사용하여 컨테이너를 생성했을때 실행되는 명령어이다. 그래서 딱 한번만 사용 할 수 있다.
여러개의 CMD가 있다면 마지막 항목의 CMD만 적용된다.
CMD의 주요 목적은 실행 컨테이너에 대한 기본값을 제공하는 것이다. 이러한 기본 값은 실행 파일을 포함하거나 실행파일을 생략할 수 있다. 하지만 이 경우 ENTRYPOINT도 함께 작성해주어야 한다.
CMD에는 3가지 형식이 있다.
CMD ["executable","param1","param2"]( exec 형식, 선호하는 형식)CMD ["param1","param2"]( ENTRYPOINT에 대한 기본 매개변수로. 이경우 둘다 JSON형식으로 작성해야한다. )CMD command param1 param2( 쉘 형태)ENTRYPOINT에는 2가지 형식이 있다.
ENTRYPOINT ["executable", "param1", "param2"]( exec 형식, 선호하는 형식)ENTRYPOINT command param1 param2( 쉘 형태)도커를 사용하다 보면 여러 컨테이너를 사용하게 된다. 하지만 여러개의 컨테이너를 전부 사용자가 관리하기는 어렵다. 그래서 이때 사용하는 것이 도커 컴포즈이다.
도커 컴포즈는 여러개의 도커 컨테이너를 하나로 묶어주는 역할을 한다.
도커 파일의 이미지는 빌드하는데 사용되고 컴포즈의 이미지는 컨테이너를 실행하는데 사용된다.
도커 파일은 도커 빌드 명령에서 새 이미지를 빌드하는 데 사용됩니다. 도커 파일에서 첫 번째 줄은 일반적으로 FROM(예: FROM nginx)으로 기본 이미지를 지정합니다. 도커 파일의 후속 RUN 행은 도커 빌드가 FROM 이미지의 컨텍스트 내에서 셸에서 실행할 추가 단계를 제공하여 새 이미지를 생성합니다. 도커 파일은 새 이미지의 이름을 지정하지 않습니다. 대신 도커 빌드의 -tome/name 옵션에 새 이미지의 이름이 지정됩니다.
docker-compose.yml 파일은 결합된 서비스의 일부로 함께 다운로드하고 실행할 이미지 그룹을 지정합니다. 예를 들어 블로그의 docker-compose.yml은 웹 서버 이미지, 응용 프로그램 이미지 및 데이터베이스 이미지로 구성될 수 있으며 이미지뿐만 아니라 통신 방법도 지정할 수 있습니다.
version: 3.9
이전버전과의 호환성을 위해 정보제공용으로만 사용된다.
꼭 작성하지 않아도 되지만, 다른 버전과의 호환을 위해 적어주면 좋다.
파일 최상단에 작성한다.
service:
service_name:
image: MY_IMAGE
build: /PATH
....
VOLUME:CONTAINER_PATH 정도로 정의 할 수 있다.해당 옵션은 각 서비스가 PID1로 실행될 수 있도록 하는 것이다.
이러한 옵션을 붙여주는 이유는 Zombie Reaping Problem 때문이다.
PID1
linux 커널을 시작할떄 실행된 첫번째 프로세스
Zombie Process
init프로세스를 제외하고 모든 프로세스는 부모 프로세스로부터 생성되고 소멸할때 wait, waitpid등 시스템콜로 호출되어 exit status를 반환한다.
반환되지 못하는 프로세스를 Zombie Process라고 한다.
자식이 먼저 죽어도 부모가 wait 호출하면 되지만, 부모가 먼저 죽으면 해당 신호를 reaping 해줄 부모가 없어진다. 이러한 문제를 init프로세스가 대신해주는데 이것도 init이 PID1이어야만 할 수 있다고 한다~
docker container는 PID1이 init 프로세스가 아니기 때문에 해당 옵션을 주어 dumb-init, tini등의 프로그램을 PID1으로 등록해주어 해당 문제를 막는 것이라고 한다~
volumes:
volume_name:
name: name_
driver: local
driver_opts:
device: /root
....
데이터를 저장할 저장소.
해당 섹션에선 여러 서비스에서 재사용 할수 있는 명명된 볼륨을 구성할 수 있다.
networks:
network_name:
driver: bridge
....
서로 통신할 수 있도록 할 수 있는 계층이다.
학습에 참고한 사이트