Post

시작하세요! 도커/쿠버네티스(2) - 도커엔진(1)

시작하세요! 도커/쿠버네티스 책 정리글입니다.

2. 도커 이미지와 컨테이너

도커의 이미지와 컨테이너는 도커 엔진의 핵심.

2.1 도커 이미지

이미지는 기존 가상머신에서 사용한 iso파일과 비슷한데, 컨테이너를 생성하고 실행할 때 읽기 전용으로 사용 된다.

이미지의 양식은 다음과 같습니다.

[저장소 이름]/[이미지 이름]:[태그]로 구성되어 있습니다.

1
2
3
kms/ubuntu:14.04
또는
ubuntu:latest
  • 저장소 이름(Repository) : 이미지가 저장된 장소. 이미지 생성시 저장소 이름을 명시할 필요가 없으므로 생략하는 경우가 있습니다.
  • 이미지 이름 : 해당 이미지가 어떤 역할을 하는지 나타냄. 반드시 설정해야 합니다.
  • 태그 : 이미지의 버전 관리, 혹은 리버전(Revision) 관리에 사용 합니다.

2.1.2 도커 컨테이너

도커의 이미지는 OS, MySQL같은 DB애플리케이션, 하둡, 스파크 등 다양한 것들이 존재합니다.

이러한 이미지로 컨테이너를 생성하면 해당 이미지의 목적에 맞는 파일이 들어 있는 파일시스템과 격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립된 공간이 생성되고, 이를 도커 컨테이너라고 부릅니다.

컨테이너는 이미지를 읽기 전용으로 사용하되 이미지에서 변경 사항은 컨테이너 계층에서 저장하므로 컨테이너에서 무엇을 하든지 원래 이미지에 영향을 주지 않습니다. 컨테이너는 각 독립된 파일시스템을 제공 받으며 호스트와 분리돼 있어서 어떤 애플리케이션을 설치하거나 삭제해도 다른 컨테이너와 호스트 변화가 없습니다.

즉 리눅스 도커 이미지로 두 개의 컨테이너를 생성한 뒤 A 컨테이너에 MySql을, B 컨테이너에 톰캣을 설치해도 각 컨테이너는 영향을 주지 않을뿐더러 호스트에도 영향을 주지 있지 않습니다.

2.2 도커 컨테이너 다루기

도커 버전을 확인.

docker -v
> Docker version 20.10.14, build a224086

첫 번째 컨테이너를 생성합니다.

docker run -i -t ubuntu:14.04

-i, -t 옵션은 컨테이너와 상호(interactive) 입출력을 가능하게 합니다. -i는 상호 입출력, -t는 tty를 활성화해서 배시(bash)셸을 사용하도록 컨테이너를 설정합니다.

와 같이 shell에 변화가 있다면 됩니다.

기본 사용자는 root이고 호스트 이름은 무작위 16진수 해시값입니다.

컨테이너를 종료할때 exitCtrl + D를 쓰지만 이는 컨테이너를 중지시켜버립니다. Ctrl + P, Q를 이용하면 컨테이너는 살리고 빠져나오므로 개발시에는 해당 커맨드를 애용합시다.

centos:7 이미지를 내려 받기 연습.

1
2
3
4
5
6
docker pull centos:7
> 7: Pulling from library/centos
6717b8ec66cd: Pull complete 
Digest: sha256:c73f515d06b0fa07bb18d8202035e739a494ce760aa73129f60f4bf2bd22b407
Status: Downloaded newer image for centos:7
docker.io/library/centos:7

docker images를 통해 존재 확인.

1
2
3
4
5
docker images

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
centos       7         c9a1fdca3387   2 months ago   301MB
ubuntu       14.04     7304c635fe52   6 months ago   187MB

docker create를 통해 이미지로 컨테이너 생성

1
2
docker create -i -t --name kmsCentos centos:7
> 233ab6341d888ceab9ee04296c8fb70858bfae8547cbaa0f78a9d4b5391453d2

--name옵션을 통해 컨테이너의 이름을 설정할 수 있습니다. 저같은 경우는 ‘kmsCentos’로 지었습니다.

create 명령어는 컨테이너를 생성할 뿐 내부로 들어가지는 않습니다.

docker start, docker attach를 통해 컨테이너를 시작하고 내부로 들어가야 합니다.

1
2
3
4
% docker start kmsCentos
> kmsCentos
% docker attach kmsCentos
[root@233ab6341d88 /]# 

docker run 명령어는 컨테이너를 생성함과 동시에 시작하기에 더 자주 사용 됩니다.

2.2.2 컨테이너 목록 확인

1
2
3
4
docker ps
kms@kmsui-MacBookPro tomcat_exam % docker ps
> CONTAINER ID   IMAGE      COMMAND       CREATED         STATUS         PORTS     NAMES
233ab6341d88   centos:7   "/bin/bash"   8 minutes ago   Up 6 minutes             kmsCentos

정지되지 않은 컨테이너만 출력하기에 Ctrl + P, Q로 입력해 빠져나온 kmsCentos컨테이너는 목록에 찍히게 됩니다.

-a옵션을 통하여 정지되지 않은 컨테이너도 출력할 수 있습니다.

  • CONTAINER ID : 컨테이너에게 자동으로 할당되는 고유한 ID, docker inspect 명령어를 통해 전체 ID를 확인할 수 있습니다.
  • IMAGE : 컨테이너를 생성할 때 사용된 이미지의 이름.
  • COMMAND : 컨테이너가 시작될 때 실행될 명령어.
  • CREATED : 컨테이너가 생성되고 난 뒤 흐른 시간
  • STATUS : 컨테이너의 상태를 나타냄. 실행중up, 종료Exited, 일시중지Pause등이 있습니다.
  • PORTS : 컨테이너가 개방한 포트와 호스트에 연결한 포트. 아무것도 설정하지 않으면 보이지 않습니다.
  • NAMES : 컨테이너의 고유한 이름입니다. 지정해줄 수 있고, 지정하지 않는다면 도커 엔진이 임의로 이름을 설정합니다.

docker rename 명령어를 통해 이름을 바꿀 수 있습니다.

2.2.3 컨테이너 삭제

한 번 삭제한 컨테이너는 복구할 수 없으므로 신중을 기해야합니다.

1
2
3
4
5
docker stop kmsCentos
> 실행중인 컨테이너는 삭제할 수 없으므로 중지 시켜야합니다. `-f`옵션을 통해 강제로 삭제할 수 있습니다.

docker rm kmsCentos
> kmsCentos

docker container prune 명령어를 통해 모든 컨테이너를 삭제할 수 있습니다.

2.2.4 컨테이너를 외부에 노출

컨테이너는 가상 IP주소를 할당 받는데, 도커의 경우는 172.17.0.x의 IP를 순차적으로 할당합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
docker run -i -t --name kms_network_test ubuntu:14.04

root@91816fd6e66d:/# 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:9 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:806 (806.0 B)  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:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

172.17.0.2를 할당받은 eth0 인터페이스와 로컬 호스트인 lo 인터페이스가 있습니다.

아무런 설정을 하지 않으면 외부에서 접근이 불가능 하므로 eth0의 IP와 포트를 호스트의 IP와 포트에 바인딩해야 합니다.

1
2
docker run -i -t --name kms_webServer -p 80:80 ubuntu:14.04
> root@f1bfd6065963:/# 

-p옵션의 [호스트포트]:[컨테이너포트] 이 양식을 통해 포트를 바인딩 해줍니다.

1
2
docker run -i -t -p 8080:8080 -p 192.168.0.1:6666:80 ubuntu:14.04
> -p옵션을 많이 쓸 수 있고, 호스트의 '6666'포트를 컨테이너의 '80'포트와 바인딩 한다는 의미도 내포
1
2
3
root@f1bfd6065963: /# apt-get update
root@f1bfd6065963: /# apt-get install apache2 -y
root@f1bfd6065963: /# service apache2 start

이후 [도커 엔진 호스트의 IP]:80 또는 localhost:80에 접근하면 아파치 웹 서버에 접근 할 수 있습니다.

아파치 웹 서버는 포트80으로 통신을 하기에 -p 80:81처럼 컨테이너 포트를 81로 지정해버리면 웹 서버에 접근하지 못하게 됩니다.

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

한 컨테이너에 데이터베이스 + 웹 서버를 넣을 수 있고, 두 컨테이너로 나눠서 하나는 데이터베이스 하나는 웹 서버로 넣을 수 있겠습니다.

후자의 경우처럼 컨테이너를 구분하는 것이 도커 이미지를 관리하고 컴포넌트의 독립성을 유지하기 쉽습니다. 도커 공식 홈페이지에서도 권장하고 있고, 한 컨테이너에 하나의 프로세스만 실행하는 것이 도커의 철학이기 때문입니다.

데이터베이스 + 워드프레스 웹 서버 컨테이너 연동

mac M1인 경우 기존 명령어로 설치가 되지 않기에 명령어를 바꿔야한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
# 기존
docker run -d \
--name wordpressdb \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=wordpress \
mysql:5.7

#M1
docker run --platform linux/amd64 \
--name wordpressdb \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=wordpress \
mysql:5.7

mySQL 컨테이너를 생성했으므로 워드프레스 웹 서버 컨테이너를 생성합니다.

1
2
3
4
5
6
7
8
docker run -d \
-e WORDPRESS_DB_HOST=mysql \
-e WORDPRESS_DB_USER=root \
-e WORDPRESS_DB_PASSWORD=password \
--name wordpress \
--link wordpressdb:mysql \
-p 80 \
wordpress

-p 80옵션을 통해 호스트의 임의의 포트와 컨테이너의 80포트를 연결하였습니다.

docker ps 명령어를 통해 어느 포트에 연결 되었는지 확인합니다.

1
2
3
docker ps
> CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                   NAMES
bd85e97e8c0d   wordpress   "docker-entrypoint.s…"   35 seconds ago   Up 33 seconds   0.0.0.0:50953->80/tcp   wordpress

50953포트에 연결되었습니다.

docekr port wordpress처럼 “docker port ‘컨테이너 명’“을 입력하면 해당 컨테이너가 사용중인 호스트의 포트가 출력 됩니다.

-d옵션을 넣어서 run을 실행하면 입출력이 없는 상태로 컨테이너를 실행합니다. 이렇게 하면 컨테이너 내부에서 프로그램이 터미널을 차지하는 포그라운드로 실행되어, 사용자의 입력을 받지 않습니다.

만약 해당 옵션을 사용하지 않는다면 하나의 터미널을 먹는 mysqld이 열리면서 단순히 프로그램이 포그라운드 모드로 동작하는 것만 지켜볼 수 있습니다.

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

환경변수를 확인하려면

1
echo ${ENVIROMENT_NAME}

을 사용하면 됩니다.

새로 만든 wordpressdb 컨테이너에 적용된 환경변수를 출력하려면 2가지 방법이 있습니다.

1
2
3
4
5
6
7
8
#1 exec -t -i 활용 터미널이 살아있음.
docker exec -i -t wordpressdb /bin/bash
root@f95d669519ce:/# echo $MYSQL_ROOT_PASSWORD
password

#2 docker exec 만 활용 결과값만 반환
docker exec wordpress ls /
# 결과값들 리턴

실제로 환경변수가 적용되었는지 컨테이너속 mysql로 이동합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 이동하는 명령어
docker exec -i -t wordpressdb /bin/bash

# mysql 확인
mysql -u root -p
> Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 7
Server version: 5.7.38 MySQL Community Server (GPL)

Copyright (c) 2000, 2022, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

--link옵션은 컨테이너끼리 접근 하는 방법중 하나입니다.

원래는 NAT로 할당받은 IP로 접근할 수 있지만, 무작위성이 강하여 매 번 변경되는 컨테이너의 IP로 접근하기 어렵습니다. 하지만 --link옵션은 내부 IP를 알 필요 없이 컨테이너에 별명(alias)으로 접근하도록 설정합니다. 또한, 의존성도 정의해주므로 실행순서도 정해줍니다.

예를들면 위의 경우 wordpressdbwordpress 컨테이너를 중지하고, 다시 wordpress를 실행시키면 다음과 같이 에러가 나옵니다.

1
2
3
docker start wordpress
> Error response from daemon: Cannot link to a non running container: /wordpressdb AS /wordpress/mysql
Error: failed to start containers: wordpress

하지만 --link옵션은 현재 ‘deprecated’된 옵션이며 추후 삭제될 가능성이 있습니다. 도커 브리지 네트워크를 사용하면 --link 옵션과 동일한 기능을 더욱 손쉽게 사용할 수 있으므로 브리지 네트워크를 사용하는것을 권장한다고 합니다.

This post is licensed under CC BY 4.0 by the author.