최근에 쿠버네티스를 공부할 일이 있어서 보고 있는데, 쿠버네티스 자체가 도커(Docker) 오케스트레이션을 해주는 툴이라 도커에 대한 개념이 없으니, 공부하기가 힘들었습니다. 그래서 이렇게 급하게 책을 사서 공부하면서 내용을 정리하고자 합니다.

해당 내용은 위키북스에서 나온 시작하세요! 도커 책을 보면서 정리한 내용입니다. 책의 내용이 매우 좋아서 강추합니다.

도커란?

도커(Docker)는 리눅스 컨테이너에 여러 기능을 추가해서 어플리케이션을 컨테이너로 쉽게 사용할 수 있게 해주는 프로젝트로 Go 언어로 만들어졌습니다.

가상 머신(Virtual Machine) VS 도커 컨테이너(Docker Container)

기존의 가상화 기술은 가상 머신(VM)이라하여 하이퍼바이저(Hypervisor)를 이용해 여러 개의 운영체제를 하나의 호스트에서 생성해 사용하는 방식이었습니다. 이 때 생성되고 관리되는 운영체제는 게스트 운영체제(Guest OS)라고 하며, 각 게스트 운영체제는 독립된 공간과 시스템 자원을 할당받아 사용합니다. 대표적인 툴로는 VirtualBox, VM Ware가 있습니다.

하지만 가상 머신은 게스트 운영체제(Guest OS)를 사용하기 위해 커널과 라이브러리 등이 포함이 되기 때문에 무겁고 용량이 큽니다, 대신에 도커 컨테이는 가상화 공간을 만들기 위해 리눅스의 자체 기능인 chroot, namespace, cgroup을 사용하기 때문에 성능 손실이 거의 없으며, 컨테이너에 필요한 커널은 호스트 운영체제의 커널을 공유해 사용 하기 때문에, 가볍습니다.


도커 설치

다음 Docker 공식 사이트에 들어갑니다.

그 다음 우측 상단의 ‘Get Started’ 버튼을 누릅니다.

그럼 아래와 같은 화면이 나오는데 자신의 시스템에 맞는 버튼을 누릅니다. 저는 Mac 환경이기 때문에 Download for Mac을 클릭하겠습니다.

그럼 다음과 같은 화면이 나타납니다. Get Docker를 눌러서 다운로드 하고 설치가까지 진행합니다.

설치가 완료가 되면 상단에 Docker가 나타나고 터미널에서 docker 명령어를 사용할 수 있게 됩니다.


도커 이미지

이미지는 컨테이너를 생성할 때 필요한 요소이며, 가상 머신을 생성할 때 사용하는 ISO 파일과 비슷한 개념입니다. 이미지는 도커 명령어로 다운로드가 되기 때문에 별도로 설치를 할 필요가 없으며 기본적으로 아래와 같이 구성됩니다.

[저장소 이름]/[이미지 이름]:[태그]

jungwoon/ubuntu:14:04

또는 저장소 이름생략이 가능해서 아래와 같이도 구성할 수 있습니다.

[이미지 이름]:[태그]

ubuntu:14:04

만약 태그 생략시 latest로 붙습니다. ex) ubuntu:latest

도커 컨테이너

이미지를 이용하면 목적별로 독립된 시스템을 및 공간을 만들 수 있는데 이를 도커 컨테이너라고 합니다. 컨테이너는 이미지를 읽기 전용으로 사용하고, 이미지에서 변경된 내용은 컨테이너 계층만 영향을 받기 때문에 이미지는 변화하지 않습니다.


도커 명령어

버전 확인하기

$ docker -v # 버전 확인
Docker version 18.09.0, build 4d60db4

도커 컨테이너 내부 쉘에서 나가기

도커 컨테이너 내부 쉘에서 나가는 방법은 두 가지가 있습니다.

  • exit : 명령어로 exit를 누르고 엔터
  • Ctrl + D : 해당 단축키를 누르면 바로 종료

위의 두 가지 방법은 컨테이너를 종료시키고 나오는 방법입니다. 아래 방법은 컨테이너를 종료시키지 않고 나오는 방법 입니다.

  • Ctrl + P, Q : 컨테이너를 종료시키지 않고 나오기 (다시 들어가려면 $ docker attach [컨테이너 명])

도커 이미지 가져오기

아래 명령어를 사용하면 도커 공식 이미지 저장소에서 이미지를 내려받습니다.

$ docker pull [이미지 이름]:[태그]

예제를 보도록 하겠습니다, 그럼 도커 공식 이미지 저장소에서 centos:7 이미지를 다운받게 됩니다.

ex)

$ docker pull centos:7

이미지 확인하기

$ docker images

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              14.04               7e4b16ae8b23        2 weeks ago         188MB
centos              7                   1e1148e4cc2c        5 weeks ago         202MB

컨테이너 생성하기

이미지로 컨테이너 생성하기

$ docker create [옵션] [이미지 이름]:[태그]

예제를 보겠습니다.

$ docker create -i -t centos:7
  • -i : 상호 입출력
  • -t : tty를 활성화하여 bash 쉘을 사용

컨테이너 실행하기

만들어진 도커 컨테이너를 실행하는 명령어 입니다.

$ docker start centos:7

컨테이너 들어가기

도커의 내부쉘로 들어가는 명령어 입니다.

$ docker attach centos:7

컨테이너 만들고 실행하기

위의 생성 -> 실행 -> 들어가기 까지 한번에 해주는 명령어 입니다.

$ docker run [옵션] [이미지 이름]:[태그] 
  • -i : 상호 입출력
  • -t : tty를 활성화하여 bash 쉘을 사용
ex)

$ docker run -i -t ubuntu:14.04

보통은 컨테이너를 생성함과 동시에 시작하기 때문에 run 명령어를 더 많이 사용합니다.


컨테이너 목록 확인

만들어진 컨테이너 목록을 확인할 수 있습니다.

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                NAMES
aab67382350b        ubuntu:14.04        "/bin/bash"         16 minutes ago      Up 16 minutes       0.0.0.0:80->80/tcp   mywebserver

대신 위의 명령어는 현재 실행중인 컨테이너 목록만 확인할 수 있기 때문에, 정지된 컨테이너까지 보고 싶으면, 아래와 같이 -a 옵션을 같이 넣어줍니다.

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
99627ff61fd7        centos:7            "/bin/bash"         42 hours ago        Exited (0) 42 hours ago                         mycentos
1758dcf92334        ubuntu:14.04        "/bin/bash"         43 hours ago        Exited (255) 25 hours ago                       determined_brattain
  • CONTAINER ID : 컨테이너에게 자동으로 할당되는 고유한 ID
  • IMAGE : 컨테이너를 생성할 때 사용된 이미지 이름
  • COMMAND : 컨맨드는 컨테이너가 시작될 때 실행될 명렁어, 기본은 /bin/bash 명령어라 명령을 쓸 수 있습니다.
  • CREATED : 컨테이너가 생성되고 난 뒤 흐른 시간
  • STATUS : 컨테이너의 상태 ex) Up(실행 중), Exited(종료), Pause(일시 중지)
  • PORTS : 컨테이너가 개방한 포트와 호스트에 연결한 포트
  • NAMES : 컨테이너의 고유한 이름, --name 옵션으로 이름을 설정하지 않으면 도커 엔진이 임의의로 설정

컨테이너 이름 변경

$ docker rename [기존 이름] [변경 하고자 하는 이름]
$ docker rename determined_brattain my_container

결과

$ docker rename determined_brattain my_container
$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                      PORTS               NAMES
99627ff61fd7        centos:7            "/bin/bash"         42 hours ago        Exited (0) 42 hours ago                         mycentos
1758dcf92334        ubuntu:14.04        "/bin/bash"         44 hours ago        Exited (255) 25 hours ago                       my_container

컨테이너 삭제

$ docker rm [컨테이너 이름]

결과

$ docker rm mycentos
mycentos

만약 container가 실행 중이면 종료하고 삭제를 하거나 -f 옵션을 이용해서 강제로 삭제를 해야합니다.

$ docker stop mycentos
$ docker rm mycentos
$ docker rm -f centos

한번에 모든 컨테이너를 삭제하려면 prune 명령어를 통해 삭제할 수 있습니다.

$  docker container prune
WARNING! This will remove all stopped containers.
Are you sure you want to continue? [y/N]

*** -q-a 옵션

  • -q : 컨테이너 ID만 출력
  • -a : 컨테이너 전체 출력

ex)

$ docker stop $(docker ps -a -q)
$ docker rnm $(docker ps -a -q)

컨테이너 외부에 노출

컨테이너는 가상 머신과 마찬가지로 가상 IP를 할당 받습니다. 테스트를 위해서 network_test란 컨테이너를 만들어 보겠습니다.

기본적으로 도커는 172.17.0.x의 IP부터 순차적으로 할당합니다.

$ docker run -i -t --name network_test ubuntu:14.04
root@7b5213595de1:/# ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:02
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:17 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:1366 (1.3 KB)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

아무 설정을 하지 않으면 기본적으로 컨테이너는 외부에서 접근할 수 없으며 도커가 설치된 호스트에서만 접근 가능합니다.

외부에 컨테이너의 어플리케이션을 노출하기 위해서는 eth0의 IP와 포트를 호스트의 IP와 포트에 바인딩해야 합니다.

테스트를 위해 아래의 새로운 컨테이너를 생성하는데 -p 옵션을 이용해 컨테이너의 포트를 호스트의 포트와 바인딩해 연결할 수 있게 설정합니다.

-p [호스트의 포트]:[컨테이너의 포트]
$ docker run -i -t --name mywebserver -p 80:80 ubuntu:14.04

만약 여러개의 포트 설정이 필요하면 -p 옵션을 여러번 사용 할 수 있고, 호스트의 특정 IP를 사용하려면 192.168.0.100:7777:80과 같이 바인딩할 IP와 포트를 직접 명시할 수도 있습니다.

예시)

$ docker run -i -t -p 3306:3306 -p 192.168.0.100:7777:80 ubuntu:14.04

테스트를 위해서 위에서 만든 mywebserver에 apache를 설치합니다.

$ apt-get update # apt-get 업데이트
$ apt-get install apache2 -y # 아파치2 설치, -y 옵션은 중간에 "설치하시겠습니까?"에 대해서 Yes라는 의미
$ service apache2 restart # 설치한 아파치2 실행

그리고 컨테이너의 IP가 아닌 자신의 로컬 호스트의 IP로 웹브라우저를 통해서 접근하면 Apache가 보입니다.