Docker continer 기본 ✏️
// INDEX
Docker Container
도커 컨테이너는 도커 이미지를 기반으로 하는 애플리케이션과 그 실행 환경을 독립되고 일관된 환경에서 실행할 수 있도록 해주는 가상화 기술이다. 컨테이너는 호스트 운영체제의 커널을 공유하면서 격리된 공간에서 애플리케이션을 실행하기 때문에, 성능 오버헤드가 적고 효율적이다.
격리된 환경이라는 것은 독립된 파일 시스템, 네트워크, PID, 사용자 등을 가진다는 의미이다. 도커 컨테이너 내부엔 여러 프로세스를 띄울 수 있지만 애플리케이션 실행을 위한 단일한 프로세스를 띄우는 것이 일반적인 컨테이너의 사용 방식이다.
리눅스 시스템의 특징 중 하나는 리눅스 시스템 부팅 시 최초로 실행되는 프로세스가 init 프로세스이며 이는 항상 PID 1번을 가진다. 1번 프로세스는 모든 프로세스의 부모 프로세스 역할을 한다. 도커 컨테이너는 하나의 독립적인 리눅스 커널을 기반으로한 시스템이기 때문에 컨테이너 내에서 실행되는 최초의 프로세스가 PID 1번을 차지하게 되며 컨테이너의 모든 자식 프로세스의 부모 프로세스로 작동한다.
일반적으로 사용자가 빌드한 도커 이미지를 기반으로 실행되는 프로세스가 PID 1번이 되며 이는 ENTRYPOINT 혹은 CMD 로 명시한 도커 파일의 명령어에서 실행되는 명령어다.
컨테이너내 실행되는 PID 1번 메인 프로세스가 종료되면 해당 컨테이너가 종료된다.
이는 메인 프로세스가 컨테이너의 라이프사이클을 관리하는 주요한 프로세스이기 때문이다.
다음 과정을 통해 도커 컨테이너의 프로세스 개념에 대해서 이해해보자.
$ docker container run --rm -p 8080:80 --name hello-nginx nginx
nginx 컨테이너를 실행한 후 exec 명령어로 내부에 실행되는 프로세스를 확인해보자.
$ docker container exec -it hello-nginx /bin/bash
# 이하 nginx 컨테이너 내부
$ ps -eaf
$ apt-get update && apt-get install -y procps
$ ps -eaf
실행중인 nginx 의 worker 와 메인 프로세스 (PID 1번) 를 확인할 수 있다. process 종료 명령어를 통해서 process 를 kill 해보자.
$ kill ${pid of nginx worker} # worker 프로세스를 종료하는 경우 worker 가 재실행되며, 컨테이너는 계속 실행 상태 유지
$ kill 1 # 컨테이너 자체가 종료됨
컨테이너 내부의 메인 프로세스를 종료하면 컨테이너가 종료된다.
Docker Container 실행을 위한 이미지 pull
도커 컨테이너 실행을 위해선 빌드한 도커 이미지가 필요하다. 이미지는 로컬에 저장되어 있을 수도, 인터넷을 통해 접근 가능한 이미지 레지스트리에 저장되어 있을 수도 있다. 도커 이미지를 이미지 레지스트리인 도커 허브에서 다운받아 로컬에 저장하는 명령어는 다음과 같다.
$ docker image pull <image name>
도커 이미지를 로컬에 저장하는 명령어를 따로 실행하지 않아도 이미지 기반으로 컨테이너 실행이 가능하다. 이는 도커가 컨테이너를 실행할 때 기본적으로 작동하는 이미지 확인 방식에 따른다.
도커는 컨테이너를 실행할 때 필요한 이미지를 가장 먼저 로컬에서 확인한다. 로컬에 있는 이미지를 확인하고 이미지가 있는 경우 해당 이미지를 사용해서 컨테이너를 실행한다. 로컬에 이미지가 없는 경우 이미지 레지스트리에서 컨테이너 실행에 필요한 이미지를 로컬에 다운받고 해당 이미지를 기반으로 컨테이너를 실행한다. 그렇기 떄문에 로컬에 실행하려는 이미지가 없는 경우 인터넷이 연결되어 있어야 한다.
# nginx 이미지가 로컬에 없는 경우 이미지를 원격에서 다운받아 실행
$ docker container run --rm -p 8080:80 --name hello-nginx nginx
Docker 의 명령어
도커는 일반적으로 cli 명령어로 사용되며, 이를 gui 환경에서 제공하는 docker desktop 과 같은 프로그램도 존재한다.
CLI 는 Command Line Interface 의 약자로, 터미널의 커맨드 명령어가 인터페이스가 되어 사용자는 이를 이용해 프로그램과 상호작용을 한다. 이는 서버 혹은 시스템 관련된 업무를 할때 gui 환경이 없이 터미널로 작업하는 방식이며 역사가 아주 깊다.
시각적인 그래픽을 통해 인터페이스를 제공하는 것은 GUI 라고 한다. Graphic User Interface 의 약자이다. 사용자들은 시각적으로 보이는 인터페이스와 상호작용을 하기 때문에 CLI 보다 편리한 사용환경을 가능하게 한다. 하지만 디테일한 시스템 설정과, 반복되는 작업에 대한 예약 등에 대한 사용이 어렵다는 제약이 있다.
도커의 루트 커맨드로 모든 도커 커맨드의 기본이 되는 커맨드이다.
$ docker --help
docker 커맨드에 대한 사용 방법을 알려주는 명령어로 해당 명령어를 실행하면 아래와 같은 내용을 볼 수 있다.

docker 커맨드를 사용할 수 있는 방법이 쭈욱 나온다. 하나씩 둘러보자.
Basic
Usage: docker [OPTION] COMMAND
A self-sufficient runtime for container
- 대괄호로 묶인
OPTION부분은 필요하면 쓰고 없으면 쓰지마세요 하는 부분이다. COMMAND는 반드시 필요한 것으로 어떤 커맨드를 사용할 수 있는지 커맨드 리스트에 나열된다.
Command
크게 4가지 범주로 지원된다.
Common CommandsManagement CommandsSwarm CommandsCommands
각각의 커맨드 또한 —help 를 이용해서 사용법을 볼 수 있으며 동일한 방식으로 사용법에 대한 안내를 제공한다.
docker run —help 예시

일반적으로 많이 사용되는 커맨드는 common command, command 로 분류되어 있으며, docker 명령어로 관리할 수 있는 자원들에 대해 제공하는 management command 로 분류할 수 있다.
위에서 본 docker run 커맨드의 Aliases(별칭 정도로 생각하면 됨)는 docker container run, docker run 으로 설정되어 있다. 이는 management command 중 하나인 container 의 하위 커맨드인 run 과 완전히 동일한 커맨드이다. 개인적으로는 management command 를 사용하는 것이 더 사용에 명확하기 때문에 선호하는 편이다.
swarm command 는 도커에서 제공하는 컨테이너 오케스트레이션 기술인 docker swarm (도커 스왐) 을 사용하기 위한 커맨드이기 때문에 아직은 몰라도 괜찮다 😊.
그럼 이미지에 관련한 커맨드와 컨테이너에 관련한 커맨드에 대해 확인해보자.

$ docker image --help
$ docker container --help
각각의 명령어의 사용법과 설명 그리고 연결해 사용할 수 있는 하위 커맨드들에 대한 내용이 나온다.
image 명령어의 하위 명령어엔 많이 봤던 pull, ls, rm 등이 있으며,
container 명령어의 하위 명령어 에는 run, start, stop 등이 있다.
Option
옵션은 일반적으로 2가지 형태가 있다. 단일 문자로 된 옵션과 긴 문자열로 된 옵션이다.
단일 문자 옵션의 역사는 유닉스부터 시작된다. 간결하고 효율성을 중시한 유닉스는 빠른 명령어 입력을 통한 사용을 목적으로 했기 때문에 짧은 버전으로 옵션을 표현했다. 여러 짧은 옵션이 결합되어 사용되는 경우도 많다. 단일 하이픈으로 사용하는 명령어가 일반적이다. 긴 문자열 옵션은 GNU 프로젝트에서 도입되었다. 명확하고 직관적인 인터페이스 제공을 위해 만들어졌으며, 가독성과 명확성이 단일 문자 옵션에 비해 올라간다. 두개의 하이픈과 하나이상의 단어로 구성된게 일반적이다.
옵션을 보면 짧은 옵션이 긴 옵션에 매핑되어 있으며 모든 긴 옵션을 짧을 옵션으로 제공하지 않기 때문에 긴 옵션의 값만 사용하는 경우도 있다.
$ docker container run --rm --name hello-docker -p 8080:8080 hello-docker:v1
예를들어 위 명령어에서 사용된 옵션에 대해서 docker container run —help 명령어를 통해 확인하면 다음과 같다.
# ...
--rm 컨테이너 종료 시 자동으로 삭제
--name string 컨테이너 이름을 명시한다.
-p, --publish list 호스트에서 오픈할 포트를 명시한다.
# ...
이처럼 다양한 옵션을 사용할 수 있으며, 자주 사용하는 옵션은 제한적이기 때문에 금방 익숙해진다.