여니의 프로그래밍 study/도커, 쿠버네티스

[2장-1] 도커 엔진

여니's 2024. 2. 4. 00:09

 

참고서적 : 시작하세요! 도커/쿠버네티스


 

(1) 도커 이미지와 컨테이너

: 도커 엔진에서 사용하는 기본단위는 이미지와 컨테이너 (핵심)

 

1. 도커 이미지

- 컨테이너를 생성할 때 필요한 요소

- 여러 개의 계층으로 된 바이너리 파일로 존재함

- 컨테이너를 생성하고 실행할 때 읽기 전용으로 사용된다

- 도커 명령어로 내려받을 수 있어 별도 설치는 필요없음

 

즉, 이미지는

컨테이너화된 애플리케이션을 실행하는데 필요한 파일,

라이브러리 및 설정과 같은 모든 요소를 포함하는

가볍고 독립적인 패키지임

 

도커에서 사용하는 이미지 이름 형식

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

ex) alicek106/ubuntu:14.04

 

저장소 : 이미지가 저장된 저장소.

단, 저장소 이름이 명시되지 않은 이미지는

도커에서 기본으로 제공하는 이미지 저장소인 "도커허브"의 공식 이미지를 의미함

생략 하는 경우도 있음

 

이미지 이름 : 이미지가 어떤 역할을 하는지 나타냄 (설정 필수)

위 예시는 우분투 컨테이너를 생성하기 위한 이미지라는 뜻

 

태그 : 이미지의 버전 관리 혹은 리비전 관리에 사용

일반적으로는 버전을 명시하지만,

태그 생략하면 도커 엔진은 이미지의 태그를 latest로 인식함

 

 


2. 도커 컨테이너

도커 이미지는

우분투, CentOS 등

기본적인 리눅스 운영체제부터

아파치 웹 서버, MySQL 데이터베이스 등의

각종 어플리케이션, 하둡이나 스파크, 스톰 등의 빅데이터 분석 도구까지

갖가지 종류가 있음

 

 

이러한 이미지로 컨테이너 생성 시

해당 이미지의 목적에 맞는 파일이 들어있는 파일 시스템과

격리된 시스템 자원 및 네트워크를 사용할 수 있는 독립된 공간이 생성된다.

그리고 이것이 바로 도커 컨테이너가 된다. 

 

 

도커 이미지로 컨테이너를 생성하는 것은

로컬 환경에서 개발 및 테스트한 어플리케이션을 패키징하고

그 패키지를 서버 또는 다른 환경에서 실행하는 개념임

 

 

도커 컨테이너는 생성될 때 사용된 도커 이미지의 종류에 따라서

맞은 설정과 파일을 가지고 있따. 

따라서 도커 이미지의 목적에 맞도록 사용되는 것이 일반적임

 

 

웹 서버 도커 이미지로부터

여러 개의 컨테이너를 생성하면

생성된 컨테이너의 개수만큼 웹 서버가 생성되고

이 컨테이너들은 외부에 웹 서비스를 제공하는데 사용된다. 

 

 

즉 여러 개의 컨테이너가 생성되면

각 컨테이너는 웹 서비스를 위한 독립된 웹 서버로 간주된다.

 

 

컨테이너는 이미지를 읽기 전용으로 사용하고

이미지에서 변경된 사항만 컨테이너 계층에 저장한다.

컨테이너에서 무엇을 하던 이미지에는 영향이 없음

 

 

생성된 각 컨테이너는

각기 독립된 파일 시스템을 제공 받으며

호스트와 분리되어 있어서

특정 컨테이너에서 어떤 애플리케이션을 설치하거나 삭제해도

다른 컨테이너와 호스트에는 변화가 없다.

 

 

(예시)

우분투 도커 이미지로 두 개의 컨테이너 생성

A 컨테이너에는 MySQL

B 컨테이너에는 아파치 웹 서버를 설치

-> 각 컨테이너는 서로 영향을 주지 않음.

 

 


(2) 도커 컨테이너 다루기

1. 컨테이너 생성

> 도커 버전 확인

docker -v

 

 

 

도커는 다양한 기능이 빠르게 업데이트 되고

새로운 버전이 배포되기 때문에

도커 엔진의 버전을 확인하는 것은 매우 중요하다. 

 

 

새로운 PC나 서버에서

도커를 사용할 때 먼저 버전부터 확인하기

 

> 컨테이너 생성하기

docker run -i -t ubuntu:14.04


# -i : 상호 입출력
# -t : tty 활성화하여 배시셸을 사용하도록 컨테이너 설정
# 위 두 옵션 중 하나라도 사용하지 않으면 셸을 정상적으로 사용할 수 없음

 

ubuntu:14.04 이미지가

로컬 도커 엔진에 존재하지 않기 때문에

도커 중앙 이미지 저장소인 도커 허브에서 

자동으로 이미지를 내려받는다. 

 

 

 

위 명령어로

컨테이너 생성 및 컨테이너 내부로 들어옴

셀의 사용자와 호스트 이름이 변경된 것을 보면

컨테이너 내부에 들어왔음을 알 수 있음

 

컨테이너 기본 사용자 : root

기본 호스트이름 : 무작위의 16진수 해시값

 

 

컨테이너와 호스트의 파일 시스템은 서로 독립적이어서

컨테이너 내에 아무것도 설치되어 있지 않음을 확인할 수 있음

 

 

 

exit 명령어를 통해 컨테이너 내부에서 호스트의 도커 환경으로 돌아옴

 

 

(컨테이너 내부에서 빠져나오는 방법)

- exit > 배시 셸을 종료함으로써 컨테이너를 정지시킴과 동시에 컨테이너에서 빠져나옴

- Ctrl + D > 컨테이너 내부에서 빠져나오면서 컨테이너 중지도 시킴

- Ctrl + P, Q > 컨테이너 정지하지 않고 빠져나오는 방법

 

즉 3번 방법만 컨테이너 중지를 시키지 않음.

플리케이션 개발하는 목적으로 컨테이너 사용시 사용하는 방법

 

CentOS 이미지 사용

도커 공식 이미지 저장소에서 centos:7 이미지 다운

 

docker pull centos:7

 

docker pull : 이미지 다운 시 사용

 

2. 컨테이너 목록 확인

docker images > 이미지 목록 출력

 

컨테이너 목록 확인

정지된 컨테이너 포함 모든 컨테이너 출력

docker ps -a

 

정지되지 않은 컨테이너만 출력함

docker ps


 

3. 컨테이너 삭제

docker rm angry_morse

 

단, 실행중인 컨테이너는 삭제가 불가하기에

컨테이너 정지 후 삭제하거나

삭제할 수 있는 옵션을 추가해야함.

 


4. 컨테이너 외부에 노출

: 컨테이너는 가상 머신과 마찬 가지로 가상 IP 주소를 할당 받음

도커는 컨테이너에 172.17.0.X의 IP 주소를 순차적으로 할당함

 

컨테이너 생성 후 ipConfig 명령어로

컨테이너의 네트워크 인터페이스 확인

 

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

# -p 옵션 : 컨테이너의 포트를 호스트의 포트와 바인딩해 연결할 수 있게 설정함
# [호스트의 포트]:[컨테이너의포트]
# 호스트의 특정 IP를 사용하려면 [호스트의 특정 IP}:[호스트의포트]:[컨테이너의 포트]

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

# 기본적으로 웹 서버는 80번 포트를 사용함.
# 따라서 컨테이너의 80번 포트를 호스트와 연결
# -p 80 으로 입력하면, 컨테이너의 80번 포트를 쓸 수 있는 호스트의 포트 중 하나와 연결
# 하지만, 어떤 포트와 연결했는지 알 수 없기에 
# docker ps 명령어를 입력해 PORTS 항목을 확인해야 함

 

 

컨테이너 생성 후 내부에 들어와서

아파치 웹 서버를 설치

 

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

 

 

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.3. Set the 'ServerName' directive globally to suppress this messag

> 오류 해결법

 

컨테이너 내부에서 실행

vi /etc/apache2/apache2.conf

Esc : 명령모드 전환

Shift : G : 파일 맨 아래로 이동

o : 개행문자 입력

i : 입력모드로 전환

Servicename 127.0.0.1 입력

Esc > :wq 입력

 

다시 service apache2 start 입력 후 실행

 

https://ethicalhacker.tistory.com/112

 

Apache2 오류 해결 "AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1.

AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 127.0.0.1. Set the 'ServerName' directive globally to suppress this message Action 'start' failed. The Apache error log may have more information. [fail] * The a

ethicalhacker.tistory.com

 

 

호스트의 IP와 포트를 컨테이너의 IP와 포트로 연결하는 개념은 매우 중요함

아파치 웹 서버는 172 대역을 가진 컨테이너의 NAT IP와 80번 포트로 서비스하므로

여기에 접근을 하려면 172.17.0.x:80의 주소로 접근해야 함

 

그러나 도커의 포트 포워딩 옵션인 -를 써서

호스트와 컨테이너를 연결했으므로

호스트의 IP와 포트를 통해 172.17.0.x:80으로 접근이 가능함

 


ip란?

Internet Protocol Address의 약자로

컴퓨터 네트워크에서 장치들이 서로를 인식하고 통신하기 위해

용하는 특수한 번호이다. 

 

 

외부 아이피란?

: 인터넷 상에서 전 세계적으로 유일한 주소를 나타낸다

 

 

내부 아이피란?

기기가 현재 포함된 네트워크 내부에서 사용하는 아이피

로컬 네트워크 내에서만 유일하게 식별된다.

 

 

포트 포워딩이란?

: 컴퓨터 네트워크에서 특정한 포트로 들어오는 네트워크 트래픽을

다른 포트로 리디렉션하는 기술임

 

 

즉 외부 아이피:포트번호와 내부 아이피:포트번호를

연결해주는 기능이다.

 

 

별도의 설정없이 외부 아이피가 접속을 시도할 때

내부에 어떤 프로세스 또는 기기와 연결할 지

알 수 없기 때문에 접근이 불가능하다. 

 

 

그래서 특정 프로세스 또는 기기에 접근하기 위해

포트 포워딩을 통해

외부 아이피 : 특정포트로 접속하면

내부 아이피: 특정 포트로 매핑해준다. 

 

 

라우터나 방화벽 같은 네트워크 장비를 사용하여

특정한 서비스나 어플리케이션을 외부에서 접근 가능하게 만들기 위해 사용함

 

 

포트 포워딩을 사용하지 않으면

외부에서 내부 네트워크에 있는 특정 서비스나 장치에

접근을 할 수 없다.

즉, 외부에서 내부로의 트래픽이 방화벽이나 라우터에서 막히게 된다.

 

 

ex) https://www.naver으로 접속하는 과정에서의 포트 포워딩 프로세스

 

1) DNS 조회

: 사용자가 해당 url 입력 시, 

브라우저는 DNS(Domain Name System) 서버에 

해당 도메인의 IP주소를 물어본다.

 

2) 네이버 서버의 외부 IP 확인

: DNS 서버는 해당 URL의 외부 IP 주소를 반환함

 

3) 브라우저의 HTTP 요청

: 브라우저는 해당 외부 아이피로 HTTP 또는 HTTPS 요청을 보냄

HTTP(80번 포트), HTTPS(443번 포트)

 

4) 라우터 및 방화벽의 역할

: 사용자의 로컬 네트워크에서 외부로의 요청은

라우터를 통과하게 된다.

이때, 라우터는 포트 포워딩 규칙에 따라 

해당 요청을 내부에서 처리할 서버로 포워딩함

 

5) 웹 서버의 응답

: 네이버 서버에서는 받은 요청에 대한 응답을 생성하여

사용자의 브라우저로 전송함

 

6) 브라우저의 응답 해석

: 브라우저는 받은 응답을 해석하고 사용자에게 화면을 표시함

 

 

외부 IP는 외부에서 내부로의 직접적인 접근을 막기 위해

라우터 등의 네트워크 장비는 사설 IP 주소를 내부 네트워크에 할당함

내부에서 통신하는 기기들은 이러한 주소를 사용하여 서로 통신함

 

 

사설 IP 주소는 인터넷에서 라우터를 통과하지 않기에

외부에서는 직접 접근이 불가함

 

(외부 IP 주소 확인법)

https://m.blog.naver.com/cmh348/222092834783

 

공인 IP(외부 IP) 주소 확인하기

공유기로 내부 ip망을 사용하고 있지 않다면, ipconfig 명령어만으로 진짜 사용 중인 ip를 알 수 있으나, ...

blog.naver.com

 

ping www.naver.com 시

request timeout이 뜸 (막아둔 듯)

다른 사이트 조회시 ip가 조회가 된다면

해당 ip가 외부 IP에 해당함

 


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

: 컨테이너에 어플리케이션 하나만 동작시키면

컨테이너 간의 독립성을 보장함과 동시에

어플리케이션의 버전 관리,

소스코드 모듈화 등이 더욱 쉬워진다. 

 

데이터베이스와 웹 서버를 컨테이너 하나에 설치할 수 있음

하지만 데이터베이스와 웹 서버를 구분하는 편이

도커 이미지를 관리하고 

컴포넌트의 독립성을 유지하기 쉬움.

도커 커뮤니티 및 공식 홈페이지에서 권장하는 구조임

하나의 컨테이너에 프로세스 하나만 실행하는 것이 도커의 철학

 

# mysql 이미지를 사용해 데이터베이스 컨테이너를 생성
docker run -d \
--name wordpressdb \
-e MYSQL_ROOT_PASSWORD=password \
-e MYSQL_DATABASE=wordpress \
mysql:5.7

# 미리 준비된 워드프레스 이미지를 이용해 워드프레스 웹 서버 컨테이너 생성
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

# 호스트의 포트 중 하나와 컨테이너의 80번 포트가 연결된다
docker ps

 

 

Unable to find image 'mysql:5.7' locally
5.7: Pulling from library/mysql
docker: no matching manifest for linux/arm64/v8 in the manifest list entries.
See 'docker run --help'.

-> M1일 경우 뜨는 에러라고 함

서버가 여러가지 버전 중 어떤 플랫폼의 버전을 가져올지 몰라 뜨는 에러로 추측됨

에러 해결을 위해 기존 명령어에 platform 인자 옵션을 추가해야 함

 

# 도커 이미지 다운로드 시, platform 옵션을 이용하여 특정 아키텍처의 이미지를 가져올 수 있음
# linux/amd64 아키텍처에서 동작하는 MySQL 5.7 이미지를 다운로드
docker pull --platform linux/amd64 mysql:5.7

 

 

 

docker port wordpress 입력 시 뜨는 포트 번호를 이용하여

호스트 IP:포트번호에 접근하면 

위 화면이 뜨게 된다.

 

mysql은 하나의 터미널을 차지하는 mysqlId를

워드프레스는 하나의 터미널을 차지하는 apache2-foreground를 실행하기에

-d 옵션을 지정해 백그라운드로 설정한 것임

 

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

컨테이너 내부에서 echo $MYSQL_ROOT_PASSWORD 입력하면

값을 출력할 수 있음

 

단, 민감한 정보를 컨테이너 내부의 환경 변수로 설정하는 것은 매우 위험하다

도커 스웜 모드의 secret이나

쿠버네티스의 secret 같은 기능을 활용해

안전하게 비밀번호를 전달해야 함

docker exec -i -t wordpressdb /bin/bash

 

 

wordpressdb 컨테이너가 중지된 상태에서

wordpress를 실행하면 오류가 난다

--link 옵션은 컨테이너 연결 및 실행순서의 의존성도 정의해줌

 

--link 옵션은 컨테이너 간에 이름을 서로 찾을 수 있도록 도와주고

추후 삭제할 수도 있음

 

'여니의 프로그래밍 study > 도커, 쿠버네티스' 카테고리의 다른 글

[2장-4] 도커 엔진  (0) 2024.03.13
[2장-3] 도커 엔진  (0) 2024.03.03
[1장] 도커란?  (1) 2024.01.21