본문 바로가기

컨테이너/Docker

[도커강의] (3) 도커의 여러가지 기능들을 확인해보자.

1. 컨테이너를 외부에 노출


컨테이너도 가상머신과 마찬가지로 가상 ip 주소를 할당 받습니다. 기본적으로 도커는 172.17.0.x 의 IP를 순차적으로 할당합니다. 하지만 이 가상 ip주소로는 우리 로컬pc의 환경에서 통신할수 없습니다.

 

다만 , 컨테이너의 포트를 호스트의 포트와 바인딩해 연결할수 있게 설정 할수 있습니다. ( -p 옵션 )

-p 옵션에 대해서 알아보기 위해 컨테이너에 아파치 웹서버를 설치하고 외부에 노출해보자.

 

$ docker run -i -t --name mywebserver -p 80:80 ubuntu:14.04

 

-p 옵션을 통해 내 로컬 pc의 80번 포트를 컨테이너의 80번 포트와 포트포워딩 했다.

즉 localhost:80으로 접속하게 되면 container의 80번 포트로 연결이 될것이다.

 

하지만 해당 컨테이너에 apache나 WEB 서버등을 설치해주어야 직관적으로 확인할수 있기 때문에 설치해준다.

 

$ apt-get update
$ apt-get install apache2 -y
$ service apache2 start

 

프로세스가 시작이 되면 localhost:80으로 접속시 아파치 홈페이지를 확인할수 있을것이다.

 

2. 컨테이너 애플리케이션 구축


다음은 도커에 database와 Web 컨테이너를 올려서 어플리케이션을 완성시켜 보자.

 

$ docker run -d --name wordpressdb \ 
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=wordpress mysql:5.7

$ docker exec -it wordpressdb /bin/bash
mysql -u root -p
# password


$ docker run -d --name wordpress -p 80 wordpress

$ docker ps
# 확인

 

첫 번째 명령어는 mysql 이미지를 사용해 데이터베이스 컨테이너를 생성한다.

두 번째 명령어는 미리 준비된 워드프레스 이미지를 이용해 워드 프레스 웹 서버 컨테이너를 생성한다

 

-d는 Detached 모드로 컨테이너를 실행한다. 컨테이너를 백그라운드에서 동작하는 애플리케이션으로써 실행하도록 설정하는것. Detached 모드인 컨테이너는 반드시 컨테이너에서 프로그램이 실행돼야 하며, 포그라운드 프로그램이 실행되지 않으면 컨테이너는 종료된다. mysql은 하나의 터미널을 차지하는 mysqld를, 워드프레스는 하나의 터미널을 차지하는 apache2-foreground를 실행한다.

 

-e 옵션은 컨테이너 내부의 환경변수를 설정한다.

 

$ docker exec -i -t wordpressdb /bin/bash
root@a93sfef334g:/$ echo $MYSQL_ROOT_PASSWORD
# password
ubuntu@ip-172-31-29-94:/var/run$ docker run -d --name wordpress2
-e WORDPRESS_DB_PASSWORD=password --link wordpressdb:mysql -p 80 wordpress

 

A 컨테이너에서 B 컨테이너로 접근하는 방법 중 가장 간단한 것은 NAT로 할당받은 내부 IP를 쓰는 것이다. 도커 엔진은 컨테이너에게 내부 IP를 172.17.0.2, 3, 4와 같이 순차적으로 할당한다. 근데 이건 컨테이너를 시작할 때마다 재할당하는 것이라 매번 변경되서 IP로 접근하기 힘들다. 따라서 --link 옵션은 내부 IP를 알 필요 없이 항상 컨테이너에 별명으로 접근하도록 설정한다. 즉 위에서 워드프레스 웹 서버 컨테이너는 wordpressdb의 IP를 몰라도 mysql이라는 호스트명으로 접근할 수 있게 된다.

 

3. 볼륨 


데이터베이스 컨테이너를 삭제하면 컨테이너에 저장되있던 데이터베이스의 데이터도 같이 삭제된다.

도커의 컨테이너는 생성과 삭제가 매우 빈번하므로, 장애나 실수로 컨테이너를 삭제하면 데이터를 복구할수 없게 된다.

이를 방지하기 위해 컨테이너의 데이터를 복제 해두는 방법들이 있다.

 

  • 호스트와 볼륨 공유
  • 볼륨 컨테이너를 활용
  • 도커 관리 볼륨

 

3-1. 호스트와 볼륨 공유

$ docker run -d \
> --name wordpressdb_hostvolume \
> -e MYSQL_ROOT_PASSWORD=password \
> -e MYSQL_DATABASE=wordpress \
> -v /home/wordpress_db:/var/lib/mysql \
> mysql:5.7

# host 디렉토리 /home/wordpress_db 가 자동으로 생성된다.

 다음 도커 명령어중에 -v 옵션은 호스트의 디렉터리와 컨테이너의 디렉터리를 공유하겠다는 뜻이다.

왼쪽이 호스트 : 오른쪽이 컨테이너의 디렉토리 형태이다.

ex ) (host directory path ) : ( container directory path )

 

 

3-2. 볼륨 컨테이너

볼륨을 사용하는 두 번째 방법은 -v 옵션으로 볼륨을 사용하는 컨테이너를 다른 컨테이너와 공유하는것. 컨테이너를 생성할 때 --volumes-from 옵션을 설정하면 -v 옵션을 적용한 컨테이너의 볼륨 디렉터리를 공유할 수 있다. 이건 직접 볼륨을 공유하는 것이 아닌 -v 옵션을 적용한 컨테이너를 통해 공유하는 것이다.

$ docker run -it \
--name volume_overide \
-v /home/wordpress_db:/home/testdir_2 \
alicek106/volume_test

root@234ijlf3234li:/$ ls /home/testdir_2/
auto.cnf ib_buffer_pool ... 
... ... ... ... ...


나와서

$ docker run -it \
--name volumes_from_container \
--volumes-from volume_overide \
ubuntu:14.04

root@123dskfj34:/$ ls /home/testdir_2/
auto.cnf ib_buffer_pool ... ...
... ... ... ... ...

이 예제는 volume_overide 컨테이너에서 볼륨을 공유받는 경우이다. volume_overide 컨테이너는 /home/testdir_2 디렉터리를 호스트와 공유하고 있으며, 이 컨테이너를 볼륨 컨테이너로서 volumes_from_container 컨테이너에 다시 공유하는 것이다.

 

 

지금까지 적용한 컨테이너 사이의 관계는 아래와 같다. 데이터를 간접적으로 공유 받는 방식이다. 느슨한 결합

 

 

3-3. 도커 볼륨

세 번째 방법은 docker volume 명령어를 사용하는 것. 볼륨을 다루는 명령어는 docker volume으로 시작하며, docker volume create 명령어로 볼륨을 생성한다. 다음 명령은 myvolume이라는 볼륨을 생성한다.

$ docker volume create --name myvolume 
myvolume

$ docker volume ls

다음 명령어를 입력해 myvolume이라는 볼륨을 사용하는 컨테이너를 생성한다.([볼륨의 이름]:[컨테이너의 공유 디렉터리])

$ docker run -it --name myvolume_1 \
-v myvolume:/root/ \
ubuntu:14.04

root@9ef3f23455:~$ echo hello, volume! >> /root/volume

/root 디렉터리에 volume이라는 파일을 생성했다. 다른 컨테이너도 myvolume 볼륨을 쓰면 볼륨을 활용한 디렉터리에 volume 파일이 존재할 것이다. 컨테이너에서 호스트로 빠져나온 뒤 또 다른 하나의 컨테이너를 생성해 확인해보자.

$ docker run -it --name myvolume_2 \
-v myvolume:/root/ \
ubuntu:14.04

root@9ef3f23455:~$ cat /root/volume
hello, volume!

docker volume 명령어로 생성한 볼륨은 아래 그림과 같은 구조로 활용된다.

볼륨은 디렉터리 하나에 상응하는 단위로서 도커 엔진에서 관리한다. 도커 볼륨도 호스트 볼륨 공유와 마찬가지로 호스트에 저장함으로써 데이터를 보존하지만 파일이 실제로 어디에 저장되는지 사용자는 알 필요가 없다.

docker inspect 명령어를 사용시 myvolume 볼륨이 실제로 어디에 저장되는지 알 수 있음.

$ docker inspect --type volume myvolume
[
    {
        "CreatedAt": "2021-05-18T00:42:03+09:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/myvolume/_data",
        "Name": "myvolume",
        "Options": {},
        "Scope": "local"
    }
]

docker volume create 명령을 별도로 입력하지 않아도 -v 옵션을 입력할 때 이를 수행하도록 설정할 수 있다.

$ docker run -it --name volume_auto \
-v /root \
ubuntu:14.04

도커 볼륨을 사용하고 있는 컨테이너를 삭제해도 볼륨이 자동으로 삭제되지는 않는다. 사용되지 않는 볼륨을 한꺼번에 삭제하려면 docker volume prune 명령어를 사용한다.

$ docker volume prune

이렇게 컨테이너가 아닌 외부에 데이터를 저장하고 컨테이너는 그 데이터로 동작하도록 설계하는 것을 stateless하다고 말한다. 컨테이너 자체는 상태가 없고 상태를 결정하는 데이터는 외부로부터 제공받는다. 컨테이너가 삭제돼도 데이터는 보존되므로 스테이트리스한 컨테이너 설계는 도커를 사용할 때 매우 바람직한 설계이다.