2.2 도커 컨테이너 다루기

컨테이너 실행해보기

  • run 명령어를 사용해서 우분투 14.04 컨테이너 실행하기

    1docker run -i -t ubuntu:14.04
    
  • 로컬에 설치된 이미지가 없기 때문에 내려받아서 컨테이너를 실행 시켜줌.

  • 사용자 이름을 보면 알 수 있듯이 컨테이너 내부에 들어온것을 볼수 있다.

  • -i 옵션으로 상호 입출력을 가능하게 한다.

  • -t 옵션으로 tty를 활성화 해서 bash shell을 사용할 수 있도록 한다.

  • 두 옵션이 없으면 shell을 정상적으로 사용할 수 없게 된다.

Untitled

  • create 명령어를 사용해서 centos 컨테이너를 생성한다.
  • --name 옵션을 통해서 컨테이너의 이름을 설정한다.

Untitled

  • start 명령어를 통해 컨테이너를 실행한다.
  • attach 명령어를 통해 컨테이너 내부로 들어간다.

Untitled

  • run 명령어는 startattach 명령어를 실행해준다.
  • 반대로 create 명령어를 실행하지 않고 컨테이너 생성까지만 수행한다.
  • runcreate 는 기본적으노 pull 명령어와 create 명령어를 수행한다.
  • pull 은 이미지가 존재하지 않을때 원격 저장소에서 이미지를 가져올 수 있도록 하며, create 는 이미지로 컨테이너를 만드는 일을 수행한다.

조회, 삭제, 종료

  • exit 입력 또는 Ctrl + D 를 입력하면 된다.

  • 이때 컨테이너가 중단되는 것에 주의한다.

  • Ctrl + P, Q 를 입력하면 컨테이너를 정지하지 않고 빠져나올 수 있다.(3개를 동시에 누르는게 아니라 P먼저 누르고 Q를 눌러야 함)

  • 도커 엔진에 존재하는 이미지의 목록 조회는 images 명령어를 사용한다.

1docker images
  • 실행중인 컨테이너 목록 확인은 ps 명령어를 사용한다.
  • COMMAND는 컨테이너가 실행될때 수행할 명령어를 뜻한다.

Untitled

  • 정지된 컨테이너까지 조회하려면 -a 옵션을 사용하면 된다.
  • 컨테이너를 중지하려면 stop 명령어를 사용하면 된다.

Untitled

  • 컨테이너 삭제는 rm 명령어를 사용하면 된다.

Untitled

  • 일괄중지는 sudo docker stop $(sudo docker ps -a -q) 명령어를 사용한다.
  • 일괄삭제는 sudo docker rm $(sudo docker ps -a -q) 명령어를 사용한다.

Untitled

컨테이너 외부 노출

  • 테스트를 위한 우분투 컨테이너를 실행한다.
1sudo docker run -i -t --name network_test ubuntu:14.04
  • 컨테이너에서 ifconfig 명령어를 실행한다.
  • 컨테이너는 기본적으로 172.17.0.x IP를 할당받는다.
  • 컨테이너는 외부에서 접속은 불가능 하며 호스트에서만 접근이 가능한 상태다.

Untitled

  • 외부 노출을 위해 eth0의 IP와 포트를 호스트의 IP와 포트에 바인딩 해야한다.
  • -p 옵션을 사용해서 [호스트의 포트]:[컨테이너의 포트] 형태로 바인딩한다.
  • -p 옵션을 여러번 사용해서 포트를 여러개 바인딩 할수도 있다.
  • 단순히 -p 80 과 같이 입력할 수 있는데 이때는 호스트의 포트가 랜덤으로 배정되기 때문에 ps 명령어를 통해서 확인해야한다.
1sudo docker run -i -t --name mywebserer -p 80:80 ubuntu:14.04
  • 우분투 컨테이너에 아파치 웹서버를 설치하고 실행한다.
1apt-get update
2apt-get install apache2 -y
3service apache2 start
  • 웹 브라우저를 통해 접속해본다.

Untitled

샘플 애플리케이션 구축

  • 데이터베이스와 웹서버를 하나의 컨테이너로 관리하기 보단 나눠서 컨테이너를 생성하고 관리하도록 하자.
  • mysql 컨테이너를 실행한다.
  • -d 옵션은 컨테이너를 백그라운드에서 동작하는 애플리케이션으로써 실행하도록 한다.
  • -e 옵션은 컨테이너 내부의 환경변수를 설정한다.
  • --link 옵션을 통해서 컨테이너간 네트워킹이 가능하도록 해준다. 컨테이너의 IP는 동적으로 할당되기 때문에 alias를 사용해서 연결한다. 컨테이너가 실행중이지 않다면 에러가 발생한다.
  • 추후 삭제될 가능성이 높은 옵션이므로 브리지 네트워크 기능으로 연결하도록 하자.
1sudo docker run -d \
2--name wordpressdb \
3-e MYSQL_ROOT_PASSWORD=password \
4-e MYSQL_DATABASE=wordpress \
5mysql:5.7
  • wordpress 웹서버 컨테이너를 실행한다.
1sudo docker run -d \
2-e WORDPRESS_DB_HOST=mysql \
3-e WORDPRESS_DB_USER=root \
4-e WORDPRESS_DB_PASSWORD=password \
5--name wordpress \
6--link wordpressdb:mysql \
7-p 80 \
8wordpress
  • wordpress 웹 서버 컨테이너와 바인딩된 호스트의 IP를 확인한다.

Untitled

  • 정상적으로 접속된다.

Untitled

컨테이너 입출력

  • -d 옵션으로 run 을 실행하면 입출력이 없는 상태로 컨테이너를 실행한다.
  • 컨테이너 내부에서 프로그램이 터미널을 차지하는 foreground로 실행되기 때문이다.
  • 따라서 -d 옵션을 사용한 컨테이너는 반드시 컨테이너 내에서 foreground로 프로그램이 실행되도록 해야한다.(터미널에 프로그램을 할당해야한다.) 그렇지 않은 경우는 컨테이너가 즉시 종료 된다.
  • ubuntu 컨테이너를 -d 옵션을 걸어서 실행하면 아래처럼 바로 종료된다.

Untitled

  • MySql 컨테이너에 -i -t 옵션을 걸면 컨테이너로 접속해서 컨테이너에서 foreground로 실행되고 있는 프로그램을 확인할 수 있다. 상호 입출력은 불가능하고 단순히 foreground로 구동되는 프로그램의 로그만 볼 수있다.
1sudo docker run -i -t \
2--name mysql_attach_test \
3-e MYSQL_ROOT_PASSWORD=password \
4-e MYSQL_DATABASE=wordpress \
5mysql:5.7

Untitled

  • 컨테이너 내부에서 echo ${환경변수명} 명령어를 입력하면 환경변수 확인이 가능하다.
  • echo 명령어를 사용하기 위해선 상호 입출력이 가능한 shell이 컨테이너에서 실행되어야한다. 위의 mysql 컨테이너는 이미 attach로 접근해도 foreground로 프로그램이 이미 실행중이다. 따라서 exec 명령어를 사용하도록 한다.
  • exec 명령어를 사용하면 컨테이너 내보의 shell을 사용할 수 있다.
1sudo docker exec -i -t mysql_attach_test /bin/bash

Untitled

  • mysql -u root -p 를 통해 password가 올바르게 적용되었는지 확인해본다.

Untitled

  • exit 명령어로 빠져나와도 컨테이너가 종료되지 않는다.

Untitled

도커 볼륨

  • 이미 생성된 이미지는 어떠한 경우로도 변경되지 않는다.
  • mysql 컨테이너를 생성했다면, 컨테이너에 운영중 생성된 데이터들이 저장된다. 이때 컨테이너를 삭제하면 컨테이너에 존재하던 데이터도 함께 삭제된다.
  • 컨테이너에 있는 데이터의 영속성을 확보하기 위해 볼륨을 활용한다.

호스트 볼륨 공유

  • -v 옵션을 통해 호스트의 /home/wordpress_db 디렉터리와 컨테이너의 /var/lib/mysql 을디렉터리를 공유한도록 한다.
  • 호스트에 해당 디렉터리가 없다면 자동으로 생성해준다.
  • 이미 호스트에 존재하는 디렉터리인 경우 호스트의 디렉터리를 컨테이너 디렉터리에 덮어쓰기 한다. 즉, 호스트가 우선순위가 더 높다.
1sudo docker run -d \
2--name wordpressdb_hostvolume \
3-e MYSQL_ROOT_PASSWORD=password \
4-e MYSQL_DATABASE=wordpress \
5-v /home/wordpress_db:/var/lib/mysql \
6mysql:5.7
  • wordpress 웹서버 컨테이너를 실행한다.
1sudo docker run -d \
2-e WORDPRESS_DB_PASSWORD=password \
3--name wordpress_hostvolume \
4--link wordpressdb_hostvolume:mysql \
5-p 80 \
6wordpress

Untitled

볼륨 컨테이너

  • -v 옵션을 사용하는 컨테이너와 연결하는 방법이다. 한마디로 -v 옵션을 사용하는 컨테이너를 브리지로 사용하는것이다
  • --volumes-from 옵션을 사용하면 된다.

Untitled

도커 볼륨

  • volume create 명령어를 통해 도커 자체에서 제공하는 볼륨 기능을 사용할 수 있다.
  • 해당 볼륨은 도커 엔진에 의해 제어된다.
1sudo docker volume create --name myvolume
  • 여러 종류의 스토리지를 사용할 수 있으며, 아래는 호스트(local)의 스토리지를 사용하도록 한다.
1sudo docker volume ls

Untitled

  • myvolume_1,myvolume_2 컨테이너가 myvolume 볼륨 컨테이너를 사용하도록 한다.
  • myvolume_1 컨테이너에 접속해서 /root 디렉토리 아래에 파일을 생성하면, myvolume_2 컨테이너의 /root 디렉토리 파일에서 확인이 가능하게 된다.
1sudo docker run -i -t --name myvolume_1 \
2-v myvolume:/root/ \
3ubuntu:14.04
1sudo docker run -i -t --name myvolume_2 \
2-v myvolume:/root/ \
3ubuntu:14.04
  • inspect 명령어를 통해서 도커 볼륨이 호스트의 어떤 디렉터리에서 저장되고 있는지 확인할 수 있다.
1sudo docker inspect --type volume myvolume

Untitled

도커 네트워크

  • 호스트에서 ifconfig 명령어를 입력하면 실행중인 컨테이너의 개수 만큼 veth가 생성된것을 확인할 수 있다.

Untitled

  • eth0는 공인 IP 또는 내부 IP가 할당되어 실제로 외부와 통신할 수 있는 호스트의 네트워크 인터페이스이다.
  • docker0는 eth0와 veth의 중간 다리 역할을 한다.
  • 컨테이너는 호스트의 veth… 과 연결되며 veth…은 docker0와 연결되어 외부와 통신할 수 있게된다. (docker0는 호스트의 eth0와 연결!)

Untitled

도커 네트워크 기능

  • 컨테이너를 생성하면 docker0 브리지를 통해서 외부와 통신할 수 있는 환경을 제공받는다.
  • 사용자의 선택에 따라 여러 네트워크 드라이버 사용이 가능하다.
  • 대표적으로 브리지(bridge), 호스트(host), 논(none), 컨테이너(container), 오버레이(overlay)가 있다.
  • docker network ls 명령어를 통해 사용가능한 네트워크를 확인할 수 있다.
  • 이미 bridge, host, none이 존재하는걸 확인할 수 있다.

Untitled

  • bridge 네트워크는 컨테이너를 생성할 때 자동으로 연결되는 docker0 브리지를 활용하도록 설정되어있다.

  • 이 네트워크는 172.17.0.x IP대역을 순차적으로 할당한다.

  • docker network inspect 명령어를 통해 네트워크의 자세한 정보를 확인할 수 있다.브리지 네트워크

    Untitled

브리지 네트워크

  • docker network create --driver bridge mybridge 명령어를 사용하면 기존의 docker0 브리지가 아닌 새로운 브리지 네트워크 생성이가능하다. (mybridge 브리지 네트워크 생성)

    Untitled

  • 컨테이너 생성시에 --net 옵션을 사용해서 생성한 브리지 사용이 가능하다.

    1docker run -i -t --name mynetwork_container \
    2--net mybridge \
    3ubuntu:14.04
    

    Untitled

  • connect disconnect 명령어를 통해서 컨테이너에 네트워크를 유동적으로 붙였다 뗐다 할수 있다.

  • 다만 브리지 네트워크, 오버레이 네트워크와 같이 특정 IP 대역을 갖는 네트워크 모드에서만 사용이 가능하다.

  • 아래와 같이 다양한 옵션을 사용해서 원하는 대역폭이나 gateway를 설정할 수 있다.( --subnet--ip-range 는 같은 대역을 가져야 한다. )

    1docker network create --driver=bridge \
    2--subnet=172.72.0.0/16 \
    3--ip-range=172.72.0.0/24 \
    4--gateway=172.72.0.1 \
    5my_custom_network
    

호스트 네트워크

  • 호스트의 네트워크 환경을 그대로 쓰는 방식이다.

  • 별도의 네트워크 생성이 필요 없으며, 기존의 host라는 이름의 네트워크를 그대로 사용한다.

    1docker run -i -t --name network_host \
    2--net host \
    3ubuntu:14.04
    
  • 컨테이너에서 ifconfig를 수행하면 호스트의 네트워크가 정보가 출력된다.

  • 사실상 호스트에서 서비스를 구동하는 것과 같은 효과를 가지게 된다.

    Untitled

논 네트워크

  • none은 아무런 네트워크를 쓰지않는 것을 뜻한다.

    1docker run -i -t --name network_none \
    2--net none \
    3ubuntu:14.04
    

    Untitled

컨테이너 네트워크

  • 다른 컨테이너의 네트워크 네임스페이스 환경을 공유할 수 있다.

  • 공유되는 속성으로는 내부IP, 네트워크 인터페이스의 맥(MAC) 주소 등이 있다.

  • --net container:[다른 컨테이너의 ID] 와 같이 작성하면 된다.

    1docker run -i -t -d --name network_container_1 ubuntu:14.04
    2
    3docker run -i -t -d --name network_container_2 \
    4--net container:network_container_1 \
    5ubuntu:14.04
    
  • 두 컨테이너의 네트워크가 같은 것을 확인할 수 있다.

    Untitled

  • 컨테이너 네트워크의 구조를 그림으로 표현하면 아래와 같다.

    Untitled

브리지 네트워크와 –net-alias

  • 브리지 타입의 네트워크와 --net-alias 옵션을 함께 사용하면 특정 호스트 이름으로 컨테이너 여러 개에 접근 할 수 있다.

     1docker run -i -t -d --name network_alias_container_1 \
     2--net mybridge \
     3--net-alias alicek106 \
     4ubuntu:14.04
     5
     6docker run -i -t -d --name network_alias_container_2 \
     7--net mybridge \
     8--net-alias alicek106 \
     9ubuntu:14.04
    10
    11docker run -i -t -d --name network_alias_container_3 \
    12--net mybridge \
    13--net-alias alicek106 \
    14ubuntu:14.04
    
  • 위 명령어를 그림으로 나타내면 아래와 같다.

  • mybridge 라는 네트워크에 속한 3개의 컨테이너는 --net-alias 옵션에 alicek106이라는 값을 입력했다.

  • 이 컨테이너의 IP는 DNS서버에 alicek106이라는 호스트 이름으로 등록된다.

  • mybridge 네트워크에 속한 컨테이너에게 alicek106이라는 호스트 이름으로 접근하면 도커 내장 DNS는 라운드로빈 방식으로 컨테이너의 IP리스트를 반환한다.

  • ping은 IP 리스트에서 첫번째 IP를 사용하므로 매번 다른 IP를 응답하게 된다. ( DNS 서버는 라운드 로빈방식으로 컨테이너의 IP 리스트를 반환하기 때문이다. )

    Untitled

MacVLAN 네트워크

  • 호스트의 네트워크 인터페이스 카드를 가상화해 물리 네트워크 환경을 컨테이너에게 동일하게 제공하는 방식이다.

  • MacVLAN을 사용하면 컨테이너도 가상의 Mac 주소를 가지게 된다.

  • 덕분에 해당 네트워크에 연결된 다른 장치와의 통신이 가능하게 된다.

  • 다만, 컨테이너A는 서버2,컨테이너B와 통신이 가능하지만 서버1(자신의 호스트)과는 통신이 불가능하다.

    Untitled

컨테이너 로깅