[Docker] 2장 : 도커 엔진_컨테이너

post-thumbnail

도커의 생태계에 있는 여러 프로그트들은 도커 엔진을 좀 더 효율적으로 사용하기 위한것이므로 핵심은 도커 엔진이다. 도커엔진에서 사용하는 기본 단위는 이미지와 컨테이너이다.

1. 이미지

(1) 개념

이미지는 컨테이너를 생성할때 필요한 요소이다. 이미지는 여러 계층으로 된 바이너리 파일로 존재하고, 컨테이너를 생성하고 실행할 때 읽기 전용으로 사용된다.

(2) 이름 구성

이미지는 도커 명령어로 내려받을 수 있는데, 보통 도커에서는 이미지의 이름을 아래와 같이 구분하여 구성한다.

👉🏻저장소 이름/이미지 이름:태그
ex) ubuntu:14.04

## 저장소 이름 : 이미지가 저장된 장소이다. 저장소 이름이 명시되지 않았다면, 해당 이미지는 도커에서 기본적으로 제공하는 이미지 저장소인 도커 허브의 공식이미지를 뜻한다. 저장소 이름은 생략하는 경우도 있다.

## 이미지 이름 : 이미지의 역할을 나타낸다. 이미지의 이름은 반드시 설정해야 한다.

## 태그 : 이미지의 버전관리, 리비전 관리에 사용한다. 일반적으로 버전을 명시하지만 생략하면, latest로 인식한다.




2. 컨테이너

(1) 개념

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

컨테이너는 이미지의 목적에 맞게 사용된다. 예를 들어, 웹 서버 도커 이미지로부터 여러개의 컨테이너를 생성하면?? 생성된 컨테이너의 수만큼 웹 서버가 생성되는 것이다.

이미지의 변경사항은 컨테이너 계층에 저장되므로, 컨테이너의 변경사항은 원본 이미지에 아무런 영향을 주지 않는다.


(2) 컨테이너 생성

//컨테이너 생성 및 실행 명령어
👉🏻docker run 옵션 이미지 이름
ex) docker run -i -t ubuntu:14.04

## -i 옵션 : 상호 입출력.
## -t 옵션 : tty를 활성화.

위 두 옵션을 통해, 컨테이너와 상호 입출력을 가능하게 하는 것이다.

ubuntu:14.04는 컨테이너를 생성하기 위한 이미지 이름이다. 이미지 저장소 이름을 명시하지 않았으므로, 도커 중앙 이미지 저장소인 도커 허브에서 자동으로 이미지를 받아온다.

run명령어는 컨테이너를 생성 및 실행과 동시에 컨테이너 내부로 들어가게 한다.

위 사진을 보면 사용자이름과 호스트이름이 바뀐것이 증거이다. 컨테이너에서 기본 사용자가 root이고, 호스트 이름은 무작위의 16진수 해시값이다. 이 값은 컨테이너의 고유한 ID의 앞의 일부분이다. (ID가 너무 길거든..)


(3) 컨테이너 빠져나오기

컨테이너 내부에서 빠져나오는 방법은 아래와같이 2가지가 있다.

☝🏻 exit을 입력하거나 ctrl+D를 입력하는것이다.
-> 이 방법은 컨테이너를 빠져나옴과 동시에 컨테이너를 정지시킨다.

✌🏻 ctrl+P+Q를 입력하는 것이다.
-> 이 방법은 단순히 컨테이너의 셸만 빠져나온다! 그래서 컨테이너 애플리케이션을 개발하는 목적으로 컨테이너를 사용할때 이 방법을 많이 쓴다.


(4) 예제 centos:7 이미지 다운

//이미지를 내려받을 때 사용하는 명령어
👉🏻 docker pull 이미지 이름

//도커 엔진에 존재하는 이미지의 목록 출력
👉🏻 docker images

컨테이너 생성 시, run명령어 말고도 create명령어를 쓸 수 있다. create명령어는 생성만 할뿐 컨테이너를 실행시키지 않는다.
--name 옵션에는 컨테이너의 이름을 설정한다.
create명령어 결과로 나온 무작위의 16진수 해시값은 컨테이너의 고유 ID다. 일반적으로 앞 12자리만 사용한다.

//mycentos 컨테이너 생성
👉🏻 docker create -i -t --name mycentos centos:7

//컨테이너 시작명령어
👉🏻 docker start 컨테이너명
//컨테이너 내부로 들어가는 명령어
👉🏻 docker attach 컨테이너명

//컨테이너에 관련된 여러 정보 확인
👉🏻 docker inspect


(5) 컨테이너 목록 확인

//실행중인 컨테이너 목록
👉🏻 docker ps
//모든 컨테이너 목록
👉🏻 docker ps -a
// 컨테이너의 정보 중 Id만 확인
👉🏻 docker inspect mycentos | grep Id

// 컨테이너 이름 변경
👉🏻 docker rename old_name new_name


(6) 컨테이너 삭제

//정지된 컨테이너 삭제가능
👉🏻 docker rm 컨테이너 이름
//실행중인 컨테이너 강제 삭제
👉🏻 docker rm -f 컨테이너 이름
//컨테이너 정지
👉🏻 docker stop 컨테이너 이름
//모든 컨테이너 삭제
👉🏻 docker container prune


(7) 컨테이너를 외부에 노출

컨테이너는 가상 IP주소를 할당받는다. 기본적으로 도커는 컨테이너에 172.17.0.x의 IP를 순차적으로 할당한다.

컨테이너 네트워크 인터페이스 확인은 컨테이너 내부로 들어가서 ifconfig 명령어로 확인!

아무런 설정없이는, 외부에서 해당 컨테이너에 접근할 수 없고, 오직 도커가 설치된 호스트에서만 접근할 수 있다.

외부에서 접근할 수 있게 변경하려면?? eth0의 IP와 포트를 호스트의 IP와 포트에 바인딩해야한다.

🐳 아파치 웹 서버 컨테이너 생성

아래와 같은 명령어로 컨테이너를 생성한다. 이 컨테이너에서는 아파치 웹 서버를 설치해 외부에 노출시킬 것이다.

// mywebserver 컨테이너 생성
👉🏻 docker run -i -t --name mywebserver -p 80:80 ubuntu:14.04

# -p옵션 : 컨테이너의 포트를 호스트의 포트와 바인딩해서 연결할 수 있게 설정한다. 만약 여러개의 포트를 외부에 개방하려면 -p 옵션을 여러번 쓰면 된다.

// -p 옵션 입력 형식
👉🏻 호스트의 포트:컨테이너의 포트

호스트와 컨테이너의 포트가 잘 연결됐는지 확인하려면, 웹 브라우저로 [호스트IP]:[컨테이너 포트]에 접근하면 된다.

// 호스트의 IP주소 확인
👉🏻 hostname -I

아래 사진과 같이 컨테이너 포트와 호스트 포트가 잘 연결된걸 확인할 수 있다.

아파치 웹 서버는 기본적으로 80번 포트를 이용하므로 여기서는 컨테이너의 80번 포트를 호스트와 연결한다. 컨테이너 생성 후 내부로 들어가서 아파치 웹 서버를 설치한다.
❗ 아파치 웹 서버가 기본적으로 80번 포트를 지원하므로 -p 80:81 이런식의 옵션은 잘못된 옵션이다.

👉🏻 apt-get update
apt-get install apache2 -y
service apache2 start

실제로 아파치 웹 서버가 설치된 것은 컨테이너 내부이므로 호스트에는 아무 영향을 주지 않는다.

호스트의 IP와 포트를 컨테이너의 IP와 포트로 연결한다는 개념은 아주 중요하다!

위에서 실습한 예제의 포트 접근 순서는 아래와 같다.

호스트IP의 80번 포트로 접근 👉🏻 80번 포트는 컨테이너의 80번 포트로 포워딩 👉🏻 웹 서버 접근


(8) 컨테이너 애플리케이션 구축

대부분의 서비스는 단일 프로그램으로 구성되지 않는다. 예를 들어, 웹 서비스도 웹 서버와 그에 필요한 데이터베이스가 있다. 웹 서버와 데이터베이스를 하나의 컨테이너에 몰아넣지 않고, 각각의 컨테이너로 만드는것이 독립성을 보장하고 관리가 수월할 것이다.
참고로 한 컨테이너에 프로세스 하나만 실행하는것이 도커의 철학이기도 하다!!

예제로 데이터베이스워드프레스 웹 서버 컨테이너를 연동해서 워드프레스 기반 블로그 서비스를 만들어보자.

// mysql이미지를 이용해 데이터베이스 컨테이너 생성하기
👉🏻 docker run -d --name wordpressdb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=wordpress mysql:5.7

## -d옵션 : Detached모드로 컨테이너를 실행. 해당 모드는 컨테이너를 백그라운드에서 동작하는 애플리케이션으로써 실행하도록 설정한다. 또한 -i -t 옵션이 없기 때문에 입출력이 없는 상태로 컨테이너를 실행하는 것이다. 컨테이너 내부에서 프로그램이 터미널을 차지하는 포그라운드로 실행돼 사용자의 입력을 받지 않는것이다.
Detached모드의 컨테이너는 반드시 컨테이너에서 프로그램이 실행되어야 하고, 포그라운드 프로그램이 실행되지 않으면 컨테이너는 종료된다....(?)

이해가 잘 안되는군... 백그라운드... 포그라운드... 먼말이고

## -e옵션 : 컨테이너 내부의 환경변수를 설정한다. 원래 비밀번호같은 중요 정보는 환경변수에 입력하면 안좋아! 도커 스웜모드의 secret이나 쿠버네티스의 secret 기능 활용해서 전달하는게 좋다!

// 미리준비된 워드프레스 이미지를 이용해 워드 프레스 웹 서버 컨테이너 생성
👉🏻 docker run -d -e WORDPRESS_DB_PASSWORD=password --name wordpress --link wordpressdb:mysql -p 80 wordpress

## --link옵션 : 컨테이너끼리 내부 IP로 접근할 수 있는데, 해당 옵션은 내부 IP를 알 필요 없이 별명으로 접근하도록 설정하는것이다. 워드프레스 웹 서버 컨테이너는 wordpressdb의 내부 IP를 몰라도 mysql이라는 호스트이름으로 요청을 전송하면 wordpressdb 컨테이너의 내부 IP에 접근할 수 있는 것이다.
❗ 해당 옵션을 쓸때 유의할점 ❗
--link에 입력된 컨테이너가 실행중이지 않거나 존재하지 않는다면 --link옵션을 적용한 컨테이너도 실행할 수 없다. 현재 예제에서 말하면, workpressdb 컨테이너를 정지시키면 wordpress컨테이너를 실행시킬때 오류가 난다. 그래서 이 옵션보다는 "도커 브리지" 네트워크를 사용하면 동일한 기능을 더욱 손쉽게 사용할 수 있어 권장하는 방향이다.

이때 워드프레스 웹 서버 컨테이너에 -p옵션으로 80을 줬기 때문에 호스트의 포트 중 하나와 컨테이너의 80번 포트가 연결된다. 호스트의 어떤 포트와 연결됐는지 확인하기 위해 docker ps 또는 아래 명령어를 확인해야 한다.

// 호스트와 바인딩된 포트만 확인하는 명령어
👉🏻 docker port 컨테이너이름(ex. wordpress)

위 사진과 같이 워드프레스 컨테이너가 성공적으로 생성된걸 확인할 수 있다.



3. 컨테이너 명령어 정리

명령어 종류기능
pull이미지 내려받기!
create컨테이너 생성만!
start컨테이너 시작!
attach컨테이너 내부로 들어가기!
runpull, crete, start 명령어 일괄적 실행 후, attach가 가능한 컨테이너라면 내부로 들어가기!
exit, ctrl+D컨테이너 빠져나가기 + 컨테이너 정지
ctrl+P+Qonly 컨테이너 빠져나가기
stop컨테이너 중지시키
inspect컨테이너, 이미지, 볼륨 등 도커의 모든 구성 단위의 정보 확인
ps진행중인 컨테이너 목록 확인
ps -a모든 컨테이너 목록 확인
ps -a -q모든 컨테이너 목록 중 ID만 확인
rename old_name new_name컨테이너 이름 변경
rm컨테이너 삭제
rm -f컨테이너 강제 삭제
container prune모든 컨테이너 삭제

컨테이너를 대상으로 하는 모든 명령어는 컨테이너의 이름대신 ID를 쓸 수도 있다.ID의 이름이 너무 길때는 그냥 ID앞의 3~4자리만 적어도 된다.

컨테이너를 삭제하면 복구할 수 없으므로 신중하게!! 참고로 실행중인 컨테이너는 삭제할 수 없으므로, 컨테이너를 정지한 뒤 삭제하거나 강제로 삭제해야된다.

TEST!!
# docker stop $(docker ps -a -q) 명령어의 의미는??
-> 모든 컨테이너를 정지해라!

🔊 볼륨 사용부터는 다음 글에서 정리하도록 하겠다!! 🔊

0개의 댓글