1. 도커 이미지

- 도커 이미지는 컨테이너 실행에 필요한 실행 파일, 라이브러리, 설정 값 등을 포함

- 이미지는 새로 만들지 않는 한 원본은 변경되지 않음

- 이미지 생성 및 실행 순서

① 애플리케이션 개발

② Dockerfile에 이미지 생성 프로세스 기입

③ 빌드하여 이미지로 생성

④ 이미지를 활용해 컨테이너 생성

⑤ 컨테이너 작동 여부 테스트

⑥ 도커허브에 업로드

⑦ ①로 돌아가기

 

1) 이미지 다운 방법

$ docker 이미지 pull 옵션 name:태그버전

docker.io : docker hub에서 기본적으로 이미지를 끌어오는 저장소 → 루트폴더처럼 굳이 적지 않아도 되는 주소로 간주

$ docker pull 192.168.31.101:9999/도커이미지

위와 같이 프라이빗 저장소를 지정하는 것도 가능하고, 주로 기업들이 이런 식으로 저장소 정보를 바꿔 사용한다.

이처럼 위와 같이 저장소 주소가 따로 들어가면 docker.io가 아닌 것을 볼 수 있다.

 

2) 이미지 내부 정보

$ docker image inspect 이미지명:버전

위 명령어를 통해 이미지 내부 정보를 JSON 형식으로 확인할 수 있다.

- 주요 정보

① Id : 이미지의 아이디

② RepoTags : 레포지토리:태그명

③ Created : 생성일자

④ GraphDriver : 이미지 레이어 정보

⑤ Architecture : CPU의 아키텍처 정보

 

- httpd:2.4 이미지 내부 정보 확인

.Os : 첫번째 계층에 있는 Os 정보만을 빠르게 찾아준다.

JSON 형식이기 때문에 위와 같이 두 개 이상 타고 들어가야 하는 정보도 있다. 

위 명령어를 통해 Config 아래 노출포트인 ExposedPorts 정보를 얻을 수 있다.

$ docker image history 이미지명:버전

마찬가지로 history를 이용해서도 이미지 정보를 얻을 수 있다.

위와 같이 history 명령어로 주요 정보에 대해 체크할 수 있다.

위와 같은 명령어를 통해 파일 형식으로 저장하는 것도 유용하다.

# cd /var/lib/docker/image/overlay2/distribution/diffid-by-digest/sha256/

이미지 구성을 위한 레이어의 계층별 파일은 distribution ID를 부여받고 위 경로에 저장된다.

# ls 번호일부* 명령을 통해 위 경로에 있는 특정 레이어 파일을 조회할 수 있다.

 

※ 하부에 깔리는 이미지는 불변(Read only)으로 만들어지고, 컨테이너는 이미지 위에 Container Layer가 입출력 가능한 계층으로 추가된다. 

→ 하부 레이어를 수정할 수는 없지만, 추가적인 레이어를 구성할 수는 있다.

 

 

2. 이미지 업로드하기

1) 도커 로그인

- 레지스트리 : Dockerfile을 빌드해서 나온 이미지 혹은 docker commit을 통해 생성한 이미지를 저장하는 사이트 자체

- 레포지토리 : 해당 사이트에 생성한 본인 명의의 저장소

- 기본적으로는 hub.docker.com 저장소를 이용하여 이미지 업로드 → docker push 명령어로 수행

- docker push 

  ① docker login : 깃허브와 깃의 관계처럼 내 레포지토리에 올리기 위한 인증

  ② docker tag : 버전별로 태그라는 것을 붙여서 식별

$ docker login
username : 계정명
password : 비밀번호
$ docker logout // 위 정보 파기

위와 같은 방식의 로그인의 경우 base64로 저장되므로 복호화가 상당히 쉽기 때문에 주의해야 한다.

안전한 인증 처리를 위해 도커허브 사이트 로그인 후 [Account Settings] - [Security] - [Access Tokens]에서 토큰 발급 

$ vi .access_token
$ cat .access_token | docker login --username 본인계정명 --password-stdin

발급받은 토큰으로 .access_token 파일을 생성하여 작성하고, 위 명령어를 사용하여 로그인한다.

위와 같이 로그인이 잘 된 것을 확인할 수 있다.

 

2) 이미지 생성 가상머신과 테스트 가상머신 분리

이미지를 생성하는 가상머신과 테스트 가상머신을 분리하기 위해 완전한 복사로 복제를 진행해준다.

$ sudo hostnamectl set-hostname hostos2

위 명령어를 통해 hostname을 변경해준 후 host가 배정받은 내부망 ip 주소 변경(여기서는 192.168.56.102로 설정) 후 재시작한다.

 

3) 본인 원격 레포지토리에 이미지 업로드

본인 소유의 레포지토리에 본인이 생성한 이미지를 업로드하기 위해서는 다음 조건을 만족해야 한다.

① 이미지가 로컬에 생성되어 있어야 한다.

② 원격 레포지토리가 존재해야 하고, 해당 레포지토리에 접근할 수 있는 아이디로 로그인이 되어있어야 한다.

먼저, 도커허브에서 위와 같이 원격 레포지토리를 생성해준다.

위와 같이 도커허브 레지스트리가 잘 생성된 것을 볼 수 있고, 해당 레지스트리에 어떻게 이미지를 업로드 하는 도커 명령어도 볼 수 있다.

실습용 이미지는 위와 같이 NGINX를 기반으로 index.html을 수정한 myweb 이미지를 1.0과 1.1 버전 2개로 준비한다.

이미지를 확인해보면 레포지토리가 붙은 이미지와 원본이미지의 IMAGE_ID 값은 동일하다는 것을 볼 수 있고, 레포지토리로 분류되는 항목에 저장소 주소(내 계정 이름)도 잘 추가된 것을 확인할 수 있다.

docker push 명령어를 통해 해당 레포지토리에 이미지를 업로드한다.

도커 허브에서 확인해보면 잘 업로드된 것을 볼 수 있다.

 

※ 요구하는 양식을 정확히 맞춘다면 push 명령어로 레포지토리가 자동 생성 되기는 하지만, 일반적으로는 도커허브에 먼저 생성해둔 후 거기에 맞춰 업로드하는 방식을 사용한다. 자동 생성되는 레지스트리는 무조건 public으로 설정된다.

 

1.1 버전도 마찬가지로 push 명령어를 사용하여 업로드해주었고, 이미 존재하는 Layer는 제외하고 변경된 부분만 push되는 것을 확인할 수 있다. 즉, 버전이 바뀌어도 기존에 사용하던 레이어는 불변이므로 특정 지점까지는 같은 레이어를 유지한다.

 

4) 올라간 이미지 다른 호스트에서 검증하기

올라간 이미지가 다른 환경에서도 돌아가는지 검증하기 위해 hostos2에서 확인해봐야 한다.

위와 같이 pull 명령어로 아까 올린 이미지를 받으면 이미지가 잘 조회되는 것을 확인할 수 있다.

또한, run 명령어로 해당 이미지를 이용하여 컨테이너를 띄워보면 잘 돌아가고 있는 것을 확인할 수 있다.

 

5) 도커허브 거치지 않고 이미지 옮겨보기

일반적으로는 도커허브를 매개로 주고받지만, 도커허브를 거치지 않고 전달해야 할 때는 도커의 save 명령어를 통해 로컬파일로 저장한 후 물리 파일을 옮겨놓고 load 명령어로 불러와서 다른 호스트에 장착시킬 수 있다.

 

 

 

6) 이미지 삭제에 유용한 명령어

이미지 전체 삭제
$ docker rmi $(docker images -q) 

특정 이미지명을 포함한 것만 삭제
$ docker rmi $(docker images | grep 이미지명)

특정 이미지명이 포함되지 않은 것만 삭제
$ docker rmi $(docker images | grep -v 이미지명)

상태가 exited인 container 전체 삭제
$ docker rm $(docker ps --filter 'status=existed' -a -q)

 

'네트워크캠퍼스 > DOCKER' 카테고리의 다른 글

CLI에서 컨테이너 관리  (0) 2024.01.31
도커 레지스트리 구축  (0) 2024.01.31
Portainer를 이용해 GUI로 컨테이너 관리  (0) 2024.01.26
로컬 환경에서 도커 다뤄보기  (0) 2024.01.25
Play with Docker  (0) 2024.01.23

※ 컨테이너를 매번 ps로 조회하지 않고 GUI로 좀 더 편리하게 관리할 수 있다.

 

먼저, pull 명령어를 통해 portainer 이미지를 받아온다.

로컬쪽과 정보를 공유시키기 위해 볼륨이라는 것을 생성한다.

$ docker run -d -p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
--restart=always \
portainer/portainer-ce

위 명령어를 통해 해당 이미지를 실행시킨다.

볼륨 연결을 통한 볼륨마운트라는 것을 통해 호스트의 파일을 컨테이너로 전송할 수 있는 통로를 마련한다.

위와 같이 ps 명령어로 조회해보면 잘 실행되고 있는 것을 확인할 수 있다.

브라우저를 열고 도커를 돌리고 있는 인스턴스 내부 ip와 포트포워딩한 포트로 접속해보면 위와 같이 계정 생성 창이 나온다.

위와 같이 계정을 생성한다. (pw:dockerubuntu)

생성 성공 시 위와 같이 환경설정과 현재 상태를 확인할 수 있다.

이와 같이 docker ps와 같은 결과를 GUI 형태로 보여주는 것을 확인할 수 있다. 

$ docker exec -it 컨테이너명 전달할내역

위 명령어 역시 대체하여 잘 사용되며 콘솔에 좀 더 편하게 접근할 수 있게 된다.

위와 같이 간단한 클릭만으로 쉘을 잘 띄워주는 것을 확인할 수 있다.

또한, 보편적으로 많이 사용하는 공식이미지의 경우 App Templates이라는 것을 이용하여 배포할 수도 있다.

'네트워크캠퍼스 > DOCKER' 카테고리의 다른 글

도커 레지스트리 구축  (0) 2024.01.31
도커 이미지 구조  (0) 2024.01.30
로컬 환경에서 도커 다뤄보기  (0) 2024.01.25
Play with Docker  (0) 2024.01.23
로컬 환경 설정 (virtualbox + ubuntuos)  (0) 2024.01.22

1. rocky linux 컨테이너로 띄워보기

$ docker pull rockylinux/rockylinux

위와 같이 pull 명령어로 로키 리눅스를 받아온다.

이미지 용량을 보면 iso 파일에 비해 훨씬 경량화되어 있는 것을 확인할 수 있다.

$ docker run -it --name=rocky-container rockylinux/rockylinux 내부에서수행할명령어

run 명령어로 특정 컨테이너를 실행하고, -it 옵션을 사용하여 사용자의 명령어를 받을 수 있는 상태로 들어가도록 한다.

※ -it 옵션 : interactive 및 tty의 약자, 컨테이너 실행 시 대화형으로 실행하고 터미널을 할당하도록 지시하는 옵션

                  → 컨테이너 내부에서 사용자와 상호작용하거나 명령어를 입력할 수 있음

위와 같이 도커 엔진을 통해 rocky linux로 명령어가 전달되고, 도커 엔진을 통해 host1 Ubuntu에 결과를 전달해준다.

$ docker run -it --name=rocky-container rockylinux/rockylinux bash

 

일회성 실행이 아닌 지속적으로 관리하고 싶다면 쉘이나 배쉬 등을 켜주는 명령어를 -it 옵션으로 넘겨주면 된다.

위와 같이 bash 쉘로 잘 들어가고 종료는 exit 명령어를 이용한다. exit으로 빠져나오는 경우는 컨테이너의 상태가 exit 상태가 된다.

위와 같이 충돌이 날 경우 컨테이너를 재기동하는 start 명령을 사용한 후 실행된 컨테이너에 exec를 이용해 명령어를 전달한다.

위와 같이 start 명령을 사용하면 up 상태로 바뀐 것을 확인할 수 있다.

$ docker exec -it rocky-container bash

이후 exec 명령어를 전달하여 재기동할 수 있고, 백그라운드에서 컨테이너를 돌게 하고 싶다면 ctrl+p+q를 입력한다.

 

 

2. 우분투 띄워보기 

마찬가지로 pull 명령어로 우분투를 설치하고 확인해보면 이미지가 경량화된 것을 볼 수 있다.

우분투의 경우 apt update를 수행해야 기본적인 기능들을 추가로 사용할 수 있고, 대신 잡아먹는 용량도 늘어난다.

ifconfig 명령어를 사용하기 위해 net-tools를 설치한 후 확인해보면 위와 같이 잘 출력되는 것을 확인할 수 있다.

 

 

3. 도커 내부 아이피 배정 순서

도커는 특별한 설정이 없다면 무조건 docker0의 ip를 게이트웨이로 삼는 특성을 갖는다.

docker0의 ip 주소가 172.17.0.1이고, 가운데 17과 0은 무작위 숫자가 부여되고, 맨 마지막 숫자는 1로 시작하고 이후 요소들은 2, 3과 같이 배정한다.

$ docker inspect 컨테이너명 | grep -i ipaddress

도커 호스트 자체에서 컨테이너들에게 배정된 내부 ip를 조회할 수 있다.

위와 같이 처음 생성했던 rocky-container는 ip 주소 마지막 숫자가 2인 것을 확인할 수 있다.

위와 같이 컨테이너 ip는 마지막 숫자만 다른 것을 확인할 수 있다.

ifconfig 조회 시 가상 이더넷이 조회되는 것을 볼 수 있고,이는 호스트와 컨테이너 사이에서 매 컨테이너마다 하나씩 가상으로 생성되어 내부망 접속을 도와주며 컨테이너 개수 파악용도로 쓸 수도 있다.

 

 

4. 이미지 실존 여부 확인하기

pull이나 run으로 다운받아 실행하려는 이미지가 실제로 있는 버전인지 파악하는 것이 중요하다.

위와 같이 dockerhub에 접속하여 document를 체크하면 된다.

이처럼 공식 마크, 인증 마크가 있는 여러 레포를 볼 수 있다.

대부분의 벤더들이 이제 OS에 사용자가 설치할 수 있는 수단을 제공하는 것도 좋지만, 컨테이너로 배포하는 것이 더 효율적이라고 판단했기 때문에 많은 서드파티들은 도커 이미지로 업데이트되어있다.

Tags 탭에서 제공되는 많은 버전을 확인할 수 있다.

또한,  overview 탭에서 Dockerfile을 제공하는 링크로 와서 아무 버전이나 클릭하면 깃허브 레포로 연결되고, 해당 이미지를 구성하기 위해 어떤 도커파일이 작성되어 있는지도 공개되어 있다.

 

 

5. alpine 버전과 그냥 버전의 차이

일반 리눅스는 iso 파일만 GB단위, 컨테이너 목적의 이미지도 용량이 크기 때문에 프로세스 구동에만 필요한 경량화 os를 사용할 수도 있음

→ alpine 리눅스

무려 5MB 정도로 해결해준다. 

즉, 용량이 중요한 상황이라면 alpine 버전을 사용하여 이미지 크기를 줄일 수 있다.

 

 

6. nginx를 활용해 오픈 포트 확인하기

pull 명령어로 nginx alpine 버전으로 받아준다.

$ docker image history 방금받은이미지

위 명령어를 수행하면 EXPOSE라는 구문과 함께 오픈 포트가 공개되어 있는 것을 확인할 수 있다.

EXPOSE는 방화벽에서 외부접근을 허용하기 위해 노출시킨 포트 번호를 의미하고 위 이미지에서는 80번 포트를 기반으로 돌아가게 설계한 것을 확인할 수 있다.

다운로드했던 해당 이미지를 실행한다.

컨테이너 삭제 시 stop 상태여야만 rm 명령어를 수행할 수 있다.

8000번 포트로 포트포워딩 진행

포트포워딩이 잘 진행되었고, 실행 시 이름을 따로 지정하지 않으면 자동으로 생성해준다.

$ docker port 컨테이너명

위와 같이 추후 포트바인딩에 대한 정보 조회도 가능하다.

$ netstat -nlp | grep 포트번호

위 명령어를 통해 호스트의 몇 번 포트가 포트바인딩에 사용되고 있는지도 조회가 가능하다.

$ ps -ef | grep 프록시번호

위에서 조회한 도커프록시의 번호를 이용하여 ps -ef 명령어를 사용하면 좀 더 상세한 정보를 얻을 수 있다.

위와 같이 해당 IP와 8000번 포트로 외부에서 접속이 가능한 것을 확인할 수 있다. (NAT 이용)

위와 같이 가상머신(내부)에서는 두 ip 모두 같은 결과를 출력해내는 것을 확인할 수 있다.

위와 같은 구조이므로 윈도우 입장에서는 host1 Ubuntu를 거쳐야만 한다.

192.68.56.101:8000 → 172.17.0.6:80으로 포트포워딩을 했기 때문에 위와 같이 접속이 가능하다.

외부에서는 172.17.0.6으로 바로 접속하는 것이 불가능하다.

 

 

7. index.html을 생성해 nginx에 적용해보기

nginx의 메인페이지를 변경하기 위해 다음과 같은 작업을 수행한다.

작업을 편리하게 하기 위해 위와 같이 markup 디렉터리 생성 후 index.html 파일을 생성해준다.

 

nginx 서버는 /usr/share/nginx/html/ 경로에 해당 파일을 저장한다.

$ docker cp 파일명 컨테이너명:/usr/share/nginx/html/index.html

호스트에서 컨테이너로 파일을 보내는 방법은 바인드마운트(잘 사용하지 않음), 볼륨마운트 등이 있지만 지금은 복사 명령어로 진행한다.

cp 명령어를 통해 현재 작업폴더에서 복사할 파일을 컨테이너의 해당 경로로 복사해준다.

서버에 다시 접속해보면 위와 같이 입력한 내용대로 잘 변경되는 것을 확인할 수 있다.

 

 

8. 갱신한 nginx 이미지 만들어보기

Dockerfile을 생성하여 직접 이미지를 만들어볼 수 있다.

FROM nginx:1.25.3-alpine # 어떤 이미지 위에 갱신할 파일을 올릴지
COPY index.html /usr/share/nginx/html/index.html # 작업중인 nginx 서버에 파일 갱신
EXPOSE 80 # 80번 포트 노출
CMD ["nginx", "-g", "daemon off;"] # nginx -g daemon off; 구문 실행

위와 같이 도커파일을 생성해준다.

$ docker build -t 이미지명(지정하기):버전명(지정하기) .

복사할 파일인 index.html과 Dockerfile을 같은 경로에 둔 후 위 명령어를 사용하면 먼저 로컬에 이미지를 설치해준다.

위와 같이 로컬에 이미지가 잘 생성된 것을 확인할 수 있다.

run으로 실행한 후 해당 포트로 접속해보면 위와 같이 잘 작동하는 것을 확인할 수 있다.

추후에는 dockerhub와 같은 원격 레포지토리에 업로드까지 하면 외부에서도 마음대로 받아서 사용이 가능하다.

 

 

9. MySQL 컨테이너 생성 및 파라미터 전달 실습

$ docker pull mysql:5.7-debian

먼저, 위와 같이 mysql 이미지를 받아준다. MySQL은 환경변수가 중요하기 때문에 공식 문서를 보고 진행하는 것이 좋다.

$ docker run -it -e MYSQL_ROOT_PASSWORD=초기비번 mysql:5.7-debian /bin/bash

위와 같이 ROOT  비번을 -e 옵션으로 환경변수 처리하여 넘겨줘야 작동한다.

위와 같이 루트계정 제어창으로 잘 넘어간 것을 확인할 수 있다.

버전 확인

위와 같이 MySQL 데몬을 기동하여 외부에서 접속 가능한 상태로 만들어준다. (MySQL 서버 실행)

아까 설정했던 비밀번호를 입력하면 위와 같이 mysql이 잘 실행되는 것을 확인할 수 있다.

위와 같이 테이블 조회, 생성 등 데이터 입출력이 모두 가능하다.

exit하면 위와 같이 mysql이 잘 종료되어 있는 것을 확인할 수 있다.

이후 docker run을 하면 새로운 컨테이너가 생성되기 때문에 다시 실행할 때는 docker start로 해줘야 한다.

$ docker start 컨테이너명
$ docker exec -it 컨테이너명 bash

start로 실행한 경우 exec로 해당 인스턴스의 bash 창으로 진입해야 다시 명령을 내릴 수 있다.

이와 같이 잘 접속이 된다.

또한, MySQL 데몬은 새로 켤 때마다 실행시켜주어야 한다.

 

 

10. 컨테이너로 띄운 DB엔진 워크벤치로 다뤄보기

$ docker run --name mariadb -e MYSQL_ROOT_PASSWORD=비번 -d -e MARIADB_DATABASE=item -p 3306:3306 mariadb:10.2

 

마리아디비를 실행하고 item이라는 데이터베이스도 같이 생성하라는 의미이다.

 

워크벤치는 오라클 사이트에서 다운받거나 DBeaver 같은 오픈소스를 사용해도 된다.

위와 같이 MariaDB에 잘 접속된 것을 확인할 수 있다.

초기에 생성했던 item이라는 데이터베이스도 잘 들어있는 것을 확인할 수 있다.

위와 같이 테이블 생성, 입력, 조회 모두 가능하다.

워크벤치에 접속하여 아까 만든 DB 등이 있는지 조회할 수 있다.

이미지 삭제 시 rmi 명령어를 이용한다.

1. 도커 이미지

1) 개요

- 도커 컨테이너를 생성하기 위한 바이너리 파일

- 도커 이미지 이름

① 저장소 이름 (Repository name)

② 이미지 이름 (Image name)

③ 이미지 태그 (Image tag) : 버전 정보나 릴리즈 태그같은 저보

 

2) 도커 이미지 받아오기

$ docker pull 이미지명 or DockerHub의 레포지토리명:버전 -기타옵션

 

 

2. 도커 컨테이너

1) 개요

- 도커 이미지를 통해 실행되는 하나의 프로세스

- 원본 저장소의 Docker File로부터 Docker Image를 내려받고, 해당 이미지를 실행하여 여러 개의 컨테이너가 실행되는 구조

- 도커 이미지 : 도커 컨테이너 = 1 : N 의 구조

- 도커 이미지는 읽기 전용으로 도커 컨테이너에서 수정이 일어나도 원본 이미지에는 영향을 주지 않음

 

2) 도커 컨테이너 실행방법

① 도커 컨테이너 생성 및 시작을 한 번에 하는 방법

$ docker run [image]

 

② 도커 컨테이너 생성과 시작을 따로하는 방법

$ docker create [image]    // 컨테이너 생성
$ docker start [container] // 컨테이너 시작

 

 

3. 도커 명령어 써보기

1) 이미지 생성

$ docker pull nginx:1.23.1-alpine

1.23.1-alpine 버전의 nginx 이미지를 받아오라는 의미

 

2) 이미지 조회

$ docker images

 

3) 컨테이너 실행

$ docker run -d -p 8001:80 --name=webserver1 nginx:1.23.1-alpine

-d : detach 모드로 해당 컨테이너가 백그라운드에서 돌아감을 의미

-p : 포트바인딩, 8001(호스트포트) 포트로 접속 시 컨테이너의 80번 포트와 연결된다는 의미

--name : 컨테이너명 지정 

 

4) 컨테이너 조회

$ docker ps

CONTAINER_ID : 랜덤하게 배정

NAMES : 랜덤하게 배정

IMAGE : 컨테이너를 띄우는 데 사용한 이미지

PORTS : 호스트포트→연동된컨테잉너 포트

 

5) 컨테이너 정지

$ docker stop

컨테이너 정지 상태 → 정지 상태인 컨테이너는 ps -a로 조회해야 함

컨테이너가 제거된 상태는 아님

 

6) 도커 도큐먼트 받아오기

$ docker run -d -p 80:80 --name=pwd-container docker/getting-started:pwd

dockerhub 사이트의 해당 레포지토리에서 받아오겠다는 의미

실행 시 pull을 진행한 후 Status 부분에 새 이미지를 생성했다고 나오는 것을 확인할 수 있다.

위와 같이 이미지가 로컬에 있는지 조사한 후 없다면 받아오고, 레이어를 겹쳐서 구성하게 된다.

매번 이미지의 모든 구성요소를  받아온다면 부담이 되기 때문에 이를 방지하기 위해 각 레이어를 부품처럼 취급한다.

1. 컨테이너 기술

 

1) 컨테이너란?

- 애플리케이션을 언제든 실행 가능하도록 필요한 모든 요소를 하나의 런타임 환경으로 패키징한 논리적 공간

- 도커 : 컨테이너를 쓸 수 있도록 도와주는 기술 중 하나

- docker에서는 Dockerfile이라는 이름의 파일(대소문자 구분)에 적힌 스크립트를 통해 구현 → 코드형 인프라

 

2) 컨테이너 기술의 역사

① Traditional Deployment

- 물리적 컴퓨터에 애플리케이션을 배포하는 형태

- 하나의 하드웨어에 여러 애플리케이션이 관리되는 경우 앱간의 라이브러리 의존성 문제 발생 가능

 

②  Virtualized Deployment

- Hypervisor : 운영체제 위에서 운영체제를 독립적으로 격리시켜 실행할 수 있도록 만드는 기술 ex) vmware, virtualbox 등

- 프로세스 개수만큼 서버를 사야할 필요가 없어짐

- Guest OS를 하나하나 올리는 것에 많은 자원이 소모되는 문제 발생

 

③ Container Deployment

- 애플리케이션과 종속 항목을 하나로 묶어 실행하게 해주는 운영 시스템을 가상화한 경량의 격리된 프로세스

- microVM이라고도 부름

- 운영체제 수준의 가상화 제공

- 독립성을 갖기 때문에 다른 컨테이너에 영향을 주지 않는 stateless 환경 제공

 

3) 컨테이너 기술의 장점

- 개인 데스크탑 뿐만 아니라 기업 내의 온프레미스 서버, AWS와 같은 퍼블릭 클라우드까지 언제 어디서든 빠르고 효율적으로 배포 가능

→ 서버구성, OS설치, 네트워크, 개발 도구 구성 등의 반복적이고 불편한 작업에 시간을 낭비하지 않고 개발 그 자체에 집중 가능

- 컨테이너는 우리가 개발한 최소한의 Image(OS+실행할 프로그램)를 통해 실행되므로 경량

→ 컨테이너 이미지 생성의 Best Practice 중 하나는 이미지 경량화

- 일반 서버의 애플리케이션 실행과 달리 프로세스 수준의 속도로 빠르게 실행할 수 있고, 한 번에 여러 개의 컨테이너를 동시에 실행 가능

→ Docker의 docker compose 기술을 통해 구현

- 어떤 OS, 어떤 환경에서도 동작 가능한 이식성 보유

- 컨테이너 자체 애플리케이션 환경에 대한 관리만 요구되므로 지속적 서버관리 비용 절감 가능

- 개발팀과 운영팀의 업무 분리로 각자의 업무와 세분화된 관리에 집중 가능

→ 컨테이너는 Devops workflow 구성에 최적

 

4) 컨테이너의 사례

- 구글 웹, 앱 서비스

- 에어비엔비 추천서비스

- 넷플릭스 추천서비스

- 당근마켓 딥러닝 기반 추천서비스

- 엔씨소프트 게임서비스

- 삼성전자 헬스케어서비스

- 타다 배차서비스

- 토스 금융서비스

 

5) 컨테이너 타입

① 시스템 (or OS) 컨테이너 : OS까지만 설치해서 실행되는 유형

- 호스트 OS 위에 Ubuntu와 같은 배포판 리눅스 Image를 통해 배포되는 컨테이너

- 또다른 VM의 형태(Hypervisor와 유사), 내부에 다양한 애플리케이션 및 라이브러리 도구를 설치&실행 가능

- ex) LXC, LXD, OpenVZ, Linux Server, BSD Jails 등

 

② 애플리케이션 컨테이너 : OS와 OS 위에서 돌아갈 애플리케이션까지 같이 설치하여 실행되는 유형

- 단일 애플리케이션 실행을 위해 해당 서비스를 패키징하고 실행하도록 설계된 컨테이너

- 3-tier 애플리케이션과 같은 경우 각 tier(frondend-backend-DB)를 개별 컨테이너로 실행하여 연결

- ex) Docker container runtime, Rocket 등

 

 

2. Docker

 

1) 도커란?

- 여러 계층의 애플리케이션을 컨테이너로 분리, 연결하여 실행하는 마이크로서비스 아키텍처 프로젝트에 유용

- 애플리케이션의 인프라는 이미지를 통해 제공하고, 퍼블릭 혹은 프라이빗하게 공유 가능

- 깃허브와 유사한 방식으로 Docker Hub에서 제공

- 제공된 Image를 기반으로 Application 서비스를 제공, 이를 컨테이너화할 수 있음

 

2) 가상화(Virtualization)란?

- 서버, 스토리지, 네트워크, 애플리케이션 등을 가상화하여 하드웨어 리소스를 효율적으로 사용하려는 목적

→ 효율적인 자원 활용, 자동화된 IT 관리, 빠른 재해 복구 가능

- 물리적 하드웨어 유지 관리 대신 소프트웨어적으로 추상화된 가상화를 통해 제한된 부분을 쉽게 관리하고 유지 가능

- 하이퍼바이저 기반의 가상머신을 통해 수행 ex) VMware, VirtualBox 등

 

3) 컨테이너 가상화 vs VM 가상화

  컨테이너 VM
공통점 실행하고자 하는 애플리케이션 프로세스 및 종속 요소와 소스 등을 패키지, 즉 이미지화하여 HostOS와 격리된 환경 제공
차이점 VM 가상화에 비해 경량이면서 호스트 운영체제의 커널을 공유하는 운영체제 수준의 가상화를 구현 → 원하는 애플리케이션 환경을 빠르게 번들링하여 패키징 실제 호스트 운영체제와 같이 별도의 GuestOS를 두고 원하는 애플리케이션을 설치하는 하드웨어 수준의 가상화를 구현
운영체제가 1개 운영체제가 적어도 2개 이상

 

※ 컨테이너는 가상머신인가?

→ Container는 hypervisor와 완전히 다른데, 궁극적으로는 hypervisor와 유사한 형태의 "가상화"를 목표로 하고 있다.

→ hypervisor는 OS 및 커널이 통째로 가상화되는 반면, container는 filesystem의 가상화만을 이룬다.

→ 컨테이너는 호스트 PC의 커널을 공유하고 따르기 때문에 init(1) 등의 프로세스가 떠있을 필요가 없으며 가상화 프로그램과는 다르게 적은 메모리 사용량, 적은 오버헤드를 보인다.

 

4) 컨테이너화(containerization) 기술

① LXC를 이용한 시스템 컨테이너화로 시작

→ cgroups, namespaces : Linux Kernel 위에서 LXC를 격리시키기 위해 필요

→ cgroup, namespace 등의 커널 기술을 공유해 컨테이너에 제공

 

※ namespaces

→ 각 게스트 머신별로 독립적인 공간을 제공하고, 서로가 충돌하지 않도록 하는 기능 (현재 리눅스 커널에서는 6가지 지원)

mnt (파일시스템 마운트)  호스트 파일시스템에 구애받지 않고 독립적으로 파일시스템을 마운트하거나 언마운트 가능
pid (프로세스) 독립적인 프로세스 공간 할당
net (네트워크) namespace 간에 network 충돌 방지
ipc (SystemV IPC) 프로세스 간의 독립적인 통신통로 할당
uts (hostname) 독립적인 hostname 할당
user (UID) 독립적인 사용자 할당

 

※ cgroups (Control Groups) 

→ 자원에 대한 제어를 가능하게 해주는 리눅스 커널의 기능

→ 메모리, CPU, I/O, 네트워크, device 노드(/dev/)를 제어

 

② containerd, runC를 이용한 도커

초기 도커는 LXC를 그대로 응용하여 사용

현재는 containerd, runC를 이용하도록 변경

- runC : 커널 기술 공유를 통해 컨테이너를 생성하도록 도와줌

- containerd : 생성된 컨테이너의 라이프사이클 관리

- dockerd : 사용자 환경에서 명령 전달

- docker 1.11 버전부터 위와 같은 구조로 작동

- containerd : OCI 구현체(주로 runC)를 이용해 컨테이너를 관리해주는 daemon

- Docker Engine 자체는 이미지, 네트워크, 디스크 등의 관리 역할

- 여기서 Docker Engine과 containerd 각각이 완전 분리

  → Docker Engine 버전을 올릴 때 Docker Engine을 재시작해도 container의 재시작 없이 사용 가능

+ Recent posts