Docker

도커는 “컨테이너”이다.

컨테이너는 애플리케이션을 실행하기 위한 독립적이고 가벼운 환경을 제공하는 기술이다. 여기에는 여러 가지 구성 요소와 자원이 포함되어 있어, 애플리케이션이 이동성 있게 실행되고 개발 및 배포가 편리하게 이루어진다. 컨테이너는 가상화 기술의 한 형태로, 여러 애플리케이션을 동일한 호스트 시스템에서 격리된 환경에서 실행할 수 있도록 해준다.

컨테이너의 주요 개념과 특징

  1. 이식성(Portability): 컨테이너는 애플리케이션 및 모든 종속성을 포함하므로 어디서든 동일한 환경에서 실행될 수 있습니다. 이식성은 개발에서 운영 환경으로, 또는 클라우드 간에 애플리케이션을 쉽게 이동시킬 수 있음을 의미한다.
  2. 격리(Isolation): 컨테이너는 호스트 시스템에서 격리된 고립된 환경을 제공한다. 각 컨테이너는 자체 파일 시스템, 네트워크, 프로세스 공간을 가지며 다른 컨테이너와 독립적으로 실행된다.
  3. 가볍고 빠른 시작: 가상 머신과 비교해 컨테이너는 더 가볍고 빠르게 시작된다. 이는 호스트 운영 체제의 커널을 공유하고 자원을 가상화하지 않기 때문이다.
  4. 환경의 일치: 개발 환경과 운영 환경이 동일하게 유지된다. 개발 시 사용한 환경을 컨테이너로 패키징하면 운영 환경에서도 동일한 조건에서 애플리케이션을 실행할 수 있다.
  5. 자동화 및 스케일링: 컨테이너는 자동화된 배포 및 스케일링이 용이하며, 필요에 따라 빠르게 복제하거나 축소할 수 있다.

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

도커 이미지(Docker Image)

도커 이미지는 컨테이너를 만드는 데 사용되는 읽기 전용(Read-only) 템플릿이다.

컨테이너 실행에 필요한 파일과 설정값 등을 포함하고 있는 도커파일을 만든 후Dockerfile을 빌드하여 이미지를 만든다.

도커 컨테이너(Docker Container)

도커이미지를 실행한 상태다.

이미지로 컨테이너를 생성하면 이미지의 목적에 맞는 파일이 들어있는 파일 시스템과

격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립된 공간이 생성된다.

이것을 도커 컨테이너라고 한다.

도커 컨테이너는 읽기 전용인 이미지에 변경된 사항을 저장하는 컨테이너 계층(Layer)에 저장한다.

a1.png

도커 이미지를 도넛 레시피에 비유한다면, 도커 컨테이너는 해당 레시피를 이용해 만든 도넛으로 비유할 수 있다.

하나의 도넛 레시피에서 여러 가지 맛의 도넛을 만들 수 있는 것과 같이, 하나의 도커 이미지로 여러 개의 도커 컨테이너 를 만들 수 있다.

또한, 기존의 도넛 레시피를 수정하게 되어도, 이미 기존 레시피로 만들어진 도넛에는 영향이 없듯이, 이처럼 도커 이미지를 변경해도 이미 실행 중인 도커 컨테이너에는 영향을 주지 않는다.

  • API 테스트 및 개발에 사용되는 도구
  • 다양한 HTTP 요청 및 응답 테스트
  • 테스트 스크립팅 및 자동화 가능

기본적인 도커 명령어

도커 명령어의 구조는 아래와 같다.

  • docker [대상] [액션]

    → [대상] :container(생략 가능),image,volume,network

    → [액션] :ls,inspect,start,run

도커 컨테이너

a2.png

docker (container) create

→ 컨테이너를 생성하고 자동으로 시작하지는 않음

root@minseoky:~# docker create --name testos centos
Unable to find image 'centos:latest' locally
latest: Pulling from library/centos
a1d0c7532777: Pull complete
Digest: sha256:a27fd8080b517143cbbbab9dfb7c8571c40d67d534bbdee55bd6c473f432b177
Status: Downloaded newer image for centos:latest
875366cc4662d6ccdc21dfbaa654ed3eee74bb54d6a2ce34333a62924f7e0272

centos 이미지를 사용해서 컨테이너를 생성해 주는 명령어다.

  • -name 옵션을 추가하여 컨테이너명은 testos로 설정했다.

→ name 옵션을 쓰지 않으면 임의의 name이 부여된다.

이미 생성된 컨테이너의 컨테이너 명을 바꾸고 싶으면docker rename [현재 이름] [바꿀 이름]명령어를 사용한다.

💡 컨테이너 명을 변경하여도 컨테이너 ID는 변경되지 않는다.

로컬 리포지토리에 이미지가 없으면 기본으로 docker hub에서 이미지를 pull 한다.

한번 pull 한 이미지는 재사용이 가능하다.

컨테이너를 생성할 때 옵션을 써줄 수도 있다.

docker create -it --name testos2 centos

해당 옵션들의 설명은 아래와 같다.

옵션 설명
-i (—interactive) 표준 입력(STDIN)을 활성화 함.컨테이너와 attach되어있지 않아도 표준 입력 유지
-t (—tty) 컨테이너에 pseudo-terminal을 할당

docker ps

→ 실행(Up) 중인 컨테이너들의 목록을 확인

docker container ls와 같음

root@minseoky:~# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
adb6732a399d   centos    "/bin/bash"   51 seconds ago   Up 50 seconds             testos2

출력된 결과의 각 항목은 다음과 같이 설명할 수 있다.

[CONTAINER ID] :

  • 컨테이너에 할당되는 고유한 컨테이너 ID
  • 전체 ID에서 12자리만 출력

[IMAGE] :

  • 컨테이너를 생성할 때 사용된 이미지

[COMMAND] :

  • 컨테이너가 시작될 때 실행될 명령어
  • docker run이나docker create명령어의 맨 끝에 새로운 명령어를 입력해서 컨테이너를 생성할 때 대체 가능

[CREATED] :

  • 컨테이너 생성 후 경과 시간

[STATUS] :

  • 컨테이너의 상태
  • 실행 중(Up), 종료(Exited), 일시 중지(Pause)

[PORTS] :

  • 컨테이너가 개방한 포트와 호스트에 연결된 포트

[NAMES] :

  • 컨테이너 이름
  • a (all) 옵션을 함께 써주면 실행 중이지 않은 컨테이너를 포함하여 전체 컨테이너 목록을 출력한다.
root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
adb6732a399d   centos    "/bin/bash"   55 seconds ago   Up 54 seconds             testos2
875366cc4662   centos    "/bin/bash"   5 hours ago      Created                   testos`
  • -no-trunc 옵션을 함께 써주면 컨테이너 ID 전체를 보여준다.
root@minseoky:~# docker ps --no-trunc
CONTAINER ID                                                       IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
adb6732a399de1d9d4d2d8e2b74d6a4c6829652c8e950c77daebe32afdc25430   centos    "/bin/bash"   5 minutes ago   Up 5 minutes             testos2`

docker start

→ 컨테이너를 시작(실행)

생성해둔 컨테이너를 시작할 수 있음

root@minseoky:~# docker start -ai testos
[root@151f3b70b5a4 /]#

컨테이너(testos)를 시작하면서-ai 옵션을 사용해 해당 컨테이너 내부로 접근하여 표준 입력을 받을 수 있도록 했다.

옵션 설명
-a (—attach) 해당 컨테이너 내부로 접근

해당 컨테이너에 접근한 상태로 exit 명령을 사용하면, /bin/bash가 종료되면서 컨테이너도 함께 종료된다.

때문에 순차적으로 Ctrl + P, Ctrl + Q를 눌러 컨테이너 실행 상태를 유지한 채로 빠져나온 후, 컨테이너가 실행 중(Up)인지 확인할 수 있다.

root@minseoky:~# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
151f3b70b5a4   centos    "/bin/bash"   44 seconds ago   Up 16 seconds             testos

docker stop

→ 실행 중인 컨테이너를 종료

root@minseoky:~# docker stop testos
testos

컨테이너가 종료(Exited)된 것을 확인할 수 있다.

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                      PORTS     NAMES
151f3b70b5a4   centos    "/bin/bash"   8 minutes ago   Exited (0) 19 seconds ago             testos`

docker run

→ 컨테이너를 시작하고 COMMAND를 실행

→ 로컬에 이미지가 있다면 해당 이미지로 실행하고, 없으면 도커허브에서 다운로드 후 실행

create + start

root@minseoky:~# docker run -dit --name test centos
5d56fc765e3780fb06f5f3d5a66935e1a087087d7b9ab69e979e830773603a81

root@minseoky:~# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED        STATUS        PORTS     NAMES
5d56fc765e37   centos    "/bin/bash"   1 second ago   Up 1 second             test
  • d 옵션을 사용해 사용자가 직접 컨테이너 안으로 접근하지 않고, 컨테이너의 COMMAND를 백그라운드로 실행할 수 있다.

컨테이너를 시작할 때, 명령어의 맨 뒤에 임의로 COMMAND를 정의할 수 있다.

root@minseoky:~# docker run -it --name date centos /bin/date
Tue Jun 28 08:56:41 UTC 2022
root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                          PORTS     NAMES
24a654120847   centos    "/bin/date"   About a minute ago   Exited (0) About a minute ago             date`

COMMAND(/bin/date)가 종료되면서 컨테이너도 함께 종료된 것을 확인할 수 있다.

shell의 환경 정보를 옵션으로 정의하는 것도 가능하다.

root@minseoky:~# docker run -it --name test -w "/tmpdir" -e "MYNAME=MINSEOKY" centos

[root@8e01dc01c6f7 tmpdir]# pwd
/tmpdir

[root@8e01dc01c6f7 tmpdir]# echo $MYNAME
MINSEOKY
옵션 설명
-w (—workdir) 컨테이너의 작업 디렉토리를 설정
-e (—env) 환경 변수 설정
—env-file=[파일명] 정의해야 하는 환경 변수가 많은 경우 특정 파일을 호출해서 설정 가능

restart 옵션을 통해 정해진 규칙에 따라 자동으로 재시작이 가능하다.

root@minseoky:~# docker run -it --name test --restart always centos
[root@8dfcdfd3c5c6 /]# exit
exit

root@minseoky:~# docker ps
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS         PORTS     NAMES
8dfcdfd3c5c6   centos    "/bin/bash"   16 seconds ago   Up 3 seconds             test`

동작 중인 컨테이너에서 exit을 하면 종료가 되어야 하는데 restart 옵션을 always로 설정했기 때문에 종료되어도 다시 시작(Up) 된 것을 확인할 수 있다.

아래의 표와 같은 restart 옵션을 사용할 수 있다.

옵션 키워드 설명
—restart no 재시작하지 않음
on-failure 종료 상태(Exited code)가 0이 아닌 경우 재시작
on-failure:횟수(n) 종료 상태(Exited code)가 0이 아닌 경우 n회만 재시작
always 항상 재시작

컨테이너를 시작할 때 CPU와 메모리 등 리소스 사용량을 제한할 수 있다.

옵션 설명
—cpus 컨테이너에서 최대 사용 가능한 cpu의 수를 지정(CPU 사용 비율 지정)
ex) –cpus=0.2 는 CPU를 0.2개(20%)만큼 사용한다는 의미
-c (—cpu-share) default 값은 1024
512라고 정의하면 프로세스들 간의 CPU 자원의 경합이 발생했을 때 다른 프로세스들(1024)의 50%만 자원 할당 가능
-m (—memory) 메모리 사용량을 제한(b, k, m, g 단위 정의

이 외에도 리소스를 제한하는 더 많은 옵션들이 있다.


docker attach

→ 컨테이너 내부에 접근하여 STDIN/STDOUT/STDERR를 사용

→ 컨테이너 PID=1 표준 입출력을 이용

root@minseoky:~# docker run -it --name test centos
[root@c8137246c2de /]# [Ctrl + p, Ctrl + q]

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS          PORTS     NAMES
c8137246c2de   centos    "/bin/bash"   29 seconds ago   Up 29 seconds             test

root@minseoky:~# docker attach test
[root@c8137246c2de /]# ps -e
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
   15 pts/0    00:00:00 ps

docker exec

→ 동작 중인 컨테이너에서 새로운 프로세스를 실행

→ COMMAND 말고 별도의 명령어를 실행

root@minseoky:~# docker run -d --name web httpd
4e02c31135d3eb2dda8dcdb8fd83b97d3aa0805ddb50235b5efbc71dfa19b604

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS        PORTS     NAMES
4e02c31135d3   httpd     "httpd-foreground"   2 seconds ago   Up 1 second   80/tcp    web

root@minseoky:~# docker exec -it web /bin/bash
root@4e02c31135d3:/usr/local/apache2#

웹서버 같은 경우는 COMMAND(PID=1)가 httpd로 정의되고, 쉘이 실행되지 않기 때문에 docker attach로 명령 입력이 불가능하다.

때문에 쉘에 접근하기 위해서는 개별적으로 실행을 해줘야 한다.


docker logs

→ 컨테이너의 PID=1 프로세스의 STDIN/STDOUT/STDERR를 출력 가능

root@minseoky:~# docker run -dit --name pingtest centos /bin/ping localhost
85421d90d372895c5cc9f0219ffd6235c3536e31c9dde1eacdd641803999d59c

root@minseoky:~# docker ps
CONTAINER ID   IMAGE     COMMAND                 CREATED         STATUS         PORTS     NAMES
85421d90d372   centos    "/bin/ping localhost"   3 seconds ago   Up 2 seconds             pingtest

root@minseoky:~# docker logs -f pingtest
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.019 ms
64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.036 ms
64 bytes from localhost (127.0.0.1): icmp_seq=3 ttl=64 time=0.069 ms

root@minseoky:~# docker logs -ft pingtest
2022-06-29T02:40:10.275963929Z PING localhost (127.0.0.1) 56(84) bytes of data.
2022-06-29T02:40:10.276917834Z 64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.019 ms
2022-06-29T02:40:11.277869637Z 64 bytes from localhost (127.0.0.1): icmp_seq=2 ttl=64 time=0.036 ms

몇 가지 옵션을 주어 로그를 다양한 방식으로 출력할 수 있다.

옵션 설명
-f (—follow) 실시간으로 로그를 추적, 출력
-t (—timestamp) 타임스탬프 출력

docker stats

→ 동작 중인 컨테이너의 상태와 사용 중인 리소스의 양을 확인할 때 사용

→ 상태 확인이 끝나면 Ctrl + C를 눌러 명령을 종료

root@minseoky:~# docker run -dit --name test --cpus=0.3 stress
e1f401b606f3c1cbee21f2bbe83a656cf22c1382495055076451ceef90aee7d4

root@minseoky:~# docker stats
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
e1f401b606f3   test      29.31%    752KiB / 12.36GiB   0.01%     906B / 0B   0B / 0B     4

부하 테스트를 할 수 있는 임의의 컨테이너(test)를 실행시킨 후, docker stats으로 확인해 보았다.

각 항목에 대한 설명이다.

[CONTAINER ID] :

  • 컨테이너 ID

[NAME] :

  • 컨테이너 이름

[CPU %] :

  • CPU 사용률

[MEM USAGE / LIMIT] :

  • 메모리 사용량 / 컨테이너에서 사용할 수 있는 메모리 제한

[MEM %] :

  • 메모리 사용률

[NET I/O] :

  • 네트워크 I/O

[BLOCK I/O] :

  • 블록 I/O

[PIDS] :

  • 사용 중인 PID의 수(프로세스의 수)

docker top

→ 동작 중인 컨테이너에서 실행되고 있는 프로세스를 확인할 때 사용

root@minseoky:~# docker run -dit --name test centos
e900da8137a077c9a82f3936899e9ac0d3f167a6a6e759cfacdcce17ef940979

root@DH:~# docker top test
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                3947                3927                0                   05:45               ?                   00:00:00            /bin/bash

컨테이너 내부 격리 환경에서 각 프로세스는 PID 1번이지만, 전체 운영체제에서의 PID가 출력된다.


docker pause/unpause

→ 컨테이너를 일시 중지하거나 일시 중지된 컨테이너를 재시작

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
e900da8137a0   centos    "/bin/bash"   6 minutes ago   Up 5 minutes             test

root@minseoky:~# docker pause test
test

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS                  PORTS     NAMES
e900da8137a0   centos    "/bin/bash"   6 minutes ago   Up 6 minutes (Paused)             test

root@minseoky:~# docker attach test
You cannot attach to a paused container, unpause it first

root@minseoky:~# docker unpause test
test

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
e900da8137a0   centos    "/bin/bash"   6 minutes ago   Up 6 minutes             test

동작 중인 컨테이너를 pause 명령어를 사용하여 일시 중지한 뒤에 attach 명령어로 접근을 시도하면 당연히 접근이 되지 않는다.

unpause 명령어로 일시 중지된 컨테이너를 재시작 해주어야 접근이 가능하다.

docker ps -a로 STATUS에 Paused가 출력되는 것을 확인할 수 있다.


docker rm

→ 컨테이너를 삭제

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED          STATUS                     PORTS     NAMES
2cbeab5acfb0   centos    "/bin/bash"   9 seconds ago    Exited (0) 8 seconds ago             test2
e900da8137a0   centos    "/bin/bash"   12 minutes ago   Up 12 minutes                        test

root@minseoky:~# docker rm test
Error response from daemon: You cannot remove a running container e900da8137a077c9a82f3936899e9ac0d3f167a6a6e759cfacdcce17ef940979. Stop the container before attempting removal or force remove

root@minseoky:~# docker rm test2
test2

root@minseoky:~# docker rm -f test
test

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

rm 명령어를 사용해 종료된 컨테이너를 삭제할 수 있다.

동작 중인(Up) 컨테이너를 삭제하려면 stop 명령어를 사용해 종료(Exited) 후 삭제하거나, rm 명령어에 -f 옵션을 사용해 삭제할 수 있다.

docker rmi [이미지명] → 이미지를 삭제

docker (container) prune

→ 종료(Exited) 된 컨테이너를 일괄적으로 삭제

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS                      PORTS     NAMES
c6044f6e3d7e   centos    "/bin/bash"   44 seconds ago       Exited (0) 43 seconds ago             test4
7486f75a31e5   centos    "/bin/bash"   51 seconds ago       Exited (0) 51 seconds ago             test3
b22e767a3965   centos    "/bin/bash"   59 seconds ago       Up 58 seconds                         test2
54ca84644b86   centos    "/bin/bash"   About a minute ago   Up About a minute                     test

root@minseoky:~# docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N] y
Deleted Containers:
c6044f6e3d7eeda4d692ecb848ec52d01d22681238d5c4d2b2f430df9ae6b06f
7486f75a31e5fb22120de3ed0bd45fa65cfcd5c940981d4625dbc241ea87150f

Total reclaimed space: 0B

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED              STATUS              PORTS     NAMES
b22e767a3965   centos    "/bin/bash"   About a minute ago   Up About a minute             test2
54ca84644b86   centos    "/bin/bash"   About a minute ago   Up About a minute             test

prune 명령어를 사용하려면 앞에 [대상]을 명시해주어야 한다.

ex) container, image, network, volume, system

동작 중인 컨테이너는 삭제되지 않고 종료된 컨테이너만 삭제합니다.

docker cp

→ 컨테이너와 호스트 간의 파일 복사

root@minseoky:~# touch example.txt
root@minseoky:~# ls
example.txt

root@minseoky:~# docker run -dit --name test centos
5e43e97c988e78202f4d6dcb2b68b153c0a3c91e80ac2bdb5b8b7ae2a39f0592

root@minseoky:~# docker ps -a
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
5e43e97c988e   centos    "/bin/bash"   6 seconds ago   Up 5 seconds             test

root@minseoky:~# docker cp ~/example.txt test:/

root@minseoky:~# docker exec test /bin/ls example.txt
example.txt

root@minseoky:~# docker cp test:/example.txt ~/example2.txt

root@minseoky:~# ls
example.txt  example2.txt

docker cp 명령어를 사용하여 컨테이너와 로컬 호스트 간의 파일을 복사할 수 있습니다. docker cp [복사할 대상] [복사시킬 대상] 구조로 사용할 수 있습니다. 컨테이너 안의 디렉터리를 지정하려면 [컨테이너명:경로]의 구조로 사용해야 합니다.

docker diff

→ 컨테이너가 생성된 시점부터 변경된 이력을 확인

→ writable layer의 변경 여부를 확인

root@minseoky:~# docker run -it --name test centos
[root@ba258fff1ae8 /]# useradd containeruser
[root@ba258fff1ae8 /]# [Ctrl + p, Ctrl + q]

root@minseoky:~# docker diff test
C /home
A /home/containeruser
A /home/containeruser/.bash_logout
A /home/containeruser/.bash_profile
A /home/containeruser/.bashrc
C /etc
A /etc/subuid-
C /etc/subgid
C /etc/passwd-
C /etc/shadow
C /etc/group
A /etc/subgid-
C /etc/subuid
C /etc/gshadow
C /etc/shadow-
C /etc/gshadow-
C /etc/passwd
C /etc/group-
C /var
C /var/log
C /var/log/lastlog
C /var/spool
C /var/spool/mail
A /var/spool/mail/containeruser

diff 명령어를 사용하여 컨테이너의 변경된 이력을 확인할 수 있다. A(Add)는 추가된 이력, C(Change)는 변경된 이력, D(Delete)는 삭제된 이력을 의미한다.