나의 공부기록

[Docker]01. 컨테이너 가상화 본문

CS/Docker

[Docker]01. 컨테이너 가상화

나의 개발자 2025. 3. 17. 17:38

컨테이너 가상화 - Docker

  • 컨테이너 가상화를 하면 Host의 H/W와 kernel을 공유받기 때문에
    ➡️ Hypervisor 가상화와 달리 Guest VM과 Guest OS를 필요로 하지 않음
  • 프로세스 수준의 격리는 논리적으로 격리가 되는 것으로, A Container에서 B Container로 넘어갈 수 있기 때문에
    ➡️ 보안에 취약
  • 자원의 오버헤드적인 측면에서 Hypervisor 가상화보다 Container 가상화가 더 빠름(유리함)
  • VM을 프로비저닝 하는 과정 없이 애플리케이션만 띄우면 되기 때문에, 속도가 훨씬 빠름
    VM  생성 과정이 애플리케이션을 생성하는 것과 비슷
  • Docker의 이미지를 만드는 것을 잘해야 함🌟 
  Hypervisor 가상화 Container 가상화
격리 수준 하드웨어 수준 프로세스  수준
자원 오버헤드가 높음 오버헤드가 낮음
보안 컨테이너 가상화에 비해 높음 하이퍼바이저에 비해 낮음
프로비저닝 속도 상대적으로 느림
guest VM부터 구성
상대적으로 빠름
호스트 H/W와 커널까지 공유
 ➡️Guest VM과 kernel 구성할 필요❌
호환성 원하는 OS 설치 가능 호스트에 종속
➡️ 리눅스 기반의 컨테이너만 가능

 

✅ 컨테이너 가상화를 위한 리눅스 기반 기술

1️⃣ chroot(Change Root)

 

  • chroot를 통해 컨테이너의 최상위 디렉토리를 변경하여, 컨테이너 내부에서 접근 가능한 디렉토리(공간)를 제한

2️⃣ Cgroup(Control Group)

  • 컨테이너 호스트의 자원을 제한
  • 하이퍼바이저의 경우 자원을 할당(2core, 2GB, 20GB)하는 개념
    ↔️ 컨테이너의 경우는 제한(RAM 2GB까지 사용 가능)을 하는 개념
  • 호스트의 모든 자원을 하나의 컨테이너가 끌어다 쓰는 것을 제한

 

컨테이너 가상화의 종류

Docker

  • 컨테이너를 관리하는데 최적화
  • 앞으로 K8s를 할 때도 계속 사용할 예정

Containerd

  • K8s를 구성하는 런타임(=Engine)으로 사용할 예정

CRIO

LXC(Linux Container)

 

 

Container 가상화 실습

더보기

1. Ubuntu-tem을 Clone ➡️ RAM 용량 증가

  • Spec
    • IP : 211.183.3.100/24
    • RAM : 4GB
  • IP  수정
root@ubuntu-tem:~# vi /etc/netplan/00-installer-config.yaml

2. Docker 설치

# Docker 다운로드
root@ubuntu-tem:~# curl -fsSL https://get.docker.com -o get-docker.sh
root@ubuntu-tem:~# ls
get-docker.sh  snap

# Docker 실행 권한 부여
# +x와 777 차이점
# +x는 기존 권한에 실행 권한 추가
# 777는 모든 권한을 모든 사용자에게 추가
root@ubuntu-tem:~# chmod +x get-docker.sh

# Docker 실행
root@ubuntu-tem:~# ./get-docker.sh 
# Executing docker install script, commit: 4c94a56999e10efcf48c5b8e3f6afea464f9108e
+ sh -c apt-get -qq update >/dev/null
  • docker 설치 확인
root@ubuntu-tem:~# docker -v
Docker version 28.0.1, build 068a01e

 

⚠️유의사항

  • docker를 설치해서 생성된 인터페이스 = docker0
  • docker0라는 NIC를 통해 어떤 네트워크가 구성됐는지 파악 가능
    ➡️ IP가 부여되어 있어야 함❗(=정상)
    ➡️ IP 부여❌ (=비정상)
  • 비정상인 상태이면, 컨테이너는 실행되는데, 컨테이너끼리나 외부로 통신이 ❌
    • 비정상인 상태면, systemctl restart docker하면 IP 부여됨
  • 리눅스 측면에서 바라본 컨테이너 네트워크(172.17.0.0/16)

3. Container 실행

  • nginx라는 Base Image 다운로드 ➡️ 이미지 생성
# = docker <container 생량> run nginx
# nginx : 이미지의 이름
root@ubuntu-tem:~# docker run nginx

Unable to find image 'nginx:latest' locally # 이미지가 존재하지❌ 다운로드

# 다운로드(Pulling) 목록 ↔️ Push
# 여러 개의 Layer = 하나의 이미지
# 변경사항 발생 ➡️ 변경된 Layer만 수정하면 됨
latest: Pulling from library/nginx
7cf63256a31a: Pull complete 
bf9acace214a: Pull complete 
513c3649bb14: Pull complete 
d014f92d532d: Pull complete 
9dd21ad5a4a6: Pull complete 
943ea0f0c2e4: Pull complete 
103f50cb3e9f: Pull complete 
Digest: sha256:9d6b58feebd2dbd3c56ab5853333d627cc6e281011cfd6050fa4bcf2072c9496
Status: Downloaded newer image for nginx:latest
  • docker 실행 ➡️ foreground 상태
    • 컨테이너가 잘 동작하려면 반드시 foreground 상태인 프로세스가 존재해야 함
      • 예시) 자바 컨테이너 : 자바가 잘 동작하기 위한 명령을 실행해줘야 함
        ➡️ java -jar app.jar
    • [Ctrl + c ] : 프로세스 종료하며 컨테이너 빠져나옴
  • docker ps : 정상동작 중인 컨테이너 상태
    • 컨테이너 이름 또는 컨테이너 ID로 특정하면 됨
    • 이름을 정하지 않으면 랜덤하게 지정됨
  • docker ps -a : 모든 컨테이너 상태 확인

 

💡컨테이너 내부에서 포어그라운드로 동작하던 프로세스가 종료되자 컨테이너가 중지됨
👉 이 차이를 이해하고 해결하는게 컨테이너 가상화에서 필수이자 가장 기본이 되는 능력임

 

4. Container 삭제 - 컨테이너 이름

# docker <container 생략> rm -f <container ID 또는 NAMES>
# -f(force) : 강제삭제, 실행 중이어도 삭제
root@ubuntu-tem:~# docker rm -f strange_hamilton

 

5. Container 생성 - 이름부여

# 이름이 test이고, baseImage가 centos7인 컨테이너
root@ubuntu-tem:~# docker run --name test centos:7
Unable to find image 'centos:7' locally
7: Pulling from library/centos
2d473b07cdd5: Pull complete 
Digest: sha256:be65f488b7764ad3638f236b7b515b3678369a5124c47b8d32916d6487418ea4
Status: Downloaded newer image for centos:7
  •  centos:7 이미지는 처음에 설계 당시, '이 컨테이너를 실행하면 "/bin/bash"라는 명령을 수행하라'라고 만들어짐 
    ➡️ docker run명령으로 컨테이너를 실행시키면서 "/bin/bash"라는 명령이 수행되었을 것임
    👉 컨테이너가 "정상동작"하려면 반드시 컨테이너 내부에서 포어그라운드로 프로세스가 실행되어야 하기 때문에, 그 조건을 충족시키지 못해서 결국 컨테이너는 stop된 상태로 존재
root@ubuntu-tem:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

# COMMAND : /bin/bash ➡️ 컨테이너가 실행될 때, 수행되는 명령어
# 단, 해당 컨테이너를 동작시키지는 않음(= 특정한 프로세스 실행❌)
root@ubuntu-tem:~# docker ps -a
CONTAINER ID   IMAGE      COMMAND       CREATED         STATUS                     PORTS     NAMES
e273f375fbbe   centos:7   "/bin/bash"   2 minutes ago   Exited (0) 2 minutes ago             test

 

6. Container 실행 시, 수행할 명령어 - COMMAND

  • COMMAND : 컨테이너를 foreground로 유지시키기 위해서 사용됨
  • 명령어를 작성하면 /bin/bash를 실행하지 않고 작성된 명령어를 실행
# 명령 옵션 ⬅️ <이미지> ➡️ COMMAND : 구분 가능
root@ubuntu-tem:~# docker run --name test centos:7 sleep 60

# 컨테이너가 실행될 때, sleep 60라는 명령어가 실행됨
root@ubuntu-tem:~# docker ps
CONTAINER ID   IMAGE      COMMAND      CREATED         STATUS         PORTS     NAMES
ffc78d357807   centos:7   "sleep 60"   5 seconds ago   Up 5 seconds             test

# 60초 이후에 컨테이너가 종료됨
# 컨테이너 내부에서 foreground를 유지시켜주던 sleep 60가 종료되면
root@ubuntu-tem:~# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
  • exec : 실행 ps -p 1 : pid가 1인 애 보여줘
    • pid 1 : 컨테이너의 동작(Status = UP)을 "담보"하는 프로세스
    • 컨테이너 동작이 하나라도 되어있어야 컨테이너가 살아있을 수 있음
root@ubuntu-tem:~# docker exec test ps -p 1

docker start : 실행

docker restart : 재실행

docker stop : 중지

 

7. Container 삭제 - PID

# container 실행
root@ubuntu-tem:~# docker run --name ntest nginx:latest

# PID로 Container 삭제
root@ubuntu-tem:~# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
c6c0a5343495   nginx:latest   "/docker-entrypoint.…"   12 seconds ago   Up 11 seconds   80/tcp    ntest
root@ubuntu-tem:~# docker rm -f c6c0a5343495
c6c0a5343495

 

➕질문 : 컨테이너의 경우엔 꼭 운영체제가 아닌, nginx나 python, java 같은 앱도 컨테이너로 만들 수 있음
➡️ 호스트의 커널을 공유 중이기 때문에 가능

 

[이미지 추가]

  • kvm의 이미지와 컨테이너 이미지가 어떤 차이가 있는지 이해하면 좋음
  • 컨테이너 이미지로 컨테이너를 띄우더라도 원래 이미지는 그대로 존 

 

 

8. 컨테이너 백그라운드 실행(리눅스 상)

# -d(detach) : 리눅스 상의 background에서 컨테이너가 실행되고 있음
# 컨테이너의 내부에서는 foreground로 실행됨(nginx 설계 상)
root@ubuntu-tem:~# docker run -d --name ntest nginx:latest
7a63340a2d25edf2d04d99b64f21239c0a5cb8c7cf4a369d0d850a689ee34b9c

# 컨테이너가 정상적으로 실행되고 있음을 확인 가능
root@ubuntu-tem:~# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS     NAMES
7a63340a2d25   nginx:latest   "/docker-entrypoint.…"   57 seconds ago   Up 57 seconds   80/tcp    ntest

 

9. 컨테이너 세부정보 확인 - Inspect

# 컨테이너의 세부정보
root@ubuntu-tem:~# docker inspect ntest

# ntest 컨테이너의 IP 정보
root@ubuntu-tem:~# docker inspect ntest | grep -i ipa
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAMConfig": null,
                    "IPAddress": "172.17.0.2",
  • container와 통신 가능 확인

 

10. 컨테이너 로그 확인 - logs

  • 일반적으로 컨테이너를 실행시켰을 때, 내부의 프로세스가 적절하게 동작하지 않아 컨테이너가 중지되는 경우가 있는데, 왜 중지됐는지 여부를 어느 정도 확인 가능
    ➡️ DB 연동❌, COMMAND에 문제가 있는 경우, 내부에서 프로세스 동작 ❌
# 컨테이너의 로그 확인
# 주로, 컨테이너가 잘 동작하지 않을 때 확인
root@ubuntu-tem:~# docker logs ntest
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh

 

11. docker network 정보 확인

#
root@ubuntu-tem:~# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
19a76ba62a7a   bridge    bridge    local # Workstation의 NAT 대역과 동일 / 외부와 통신 가능
9754215ebb6d   host      host      local # 호스트 내에서만 통신
acc770ab6373   none      null      local # 네트워크❌

root@ubuntu-tem:~# docker network inspect bridge

 

12. docker image 정보 확인

  • 우리가 pull해온 두 개의 이미지(nginx:latest, centos:7은 도커허브에서 가져온 Official한 이미지)
root@ubuntu-tem:~# docker image ls
# REGISTRY : 도서관 ( docker hub, AWS ECR, 사설 등...)
# REPOSITORY : 책장 
# TAG : 책
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
nginx        latest    b52e0b094bc0   5 weeks ago   192MB
centos       7         eeb6ee3f44bd   3 years ago   204MB

 

13. 컨테이너 내부 명령 수행 - 리눅스

root@ubuntu-tem:~# docker <container> exec <명령을 수행할 컨테이너> <명령>

# ntest라는 컨테이너에 ls라는 명령어 실행
root@ubuntu-tem:~# docker exec ntest ls
bin
boot
dev
docker-entrypoint.d
docker-entrypoint.sh
etc
home
lib
lib64

 

14. 컨테이너 내부 접속 - 컨테이너

# -i(interactive) : 상호작용, -t(terminal)
# 해당 컨테이너와 터미널로 작용하겠음 = 터미널로 접속하겠다.
root@ubuntu-tem:~# docker run -it --name cent centos:7 bash
# a1ee8de1c265 : 컨테이너 ID
# cent라는 컨테이너를 실행함과 동시에, 내부로 들어옴
[root@a1ee8de1c265 /]#

 

💡컨테이너 빠져나오는 방법

1️⃣ Ctrl + pq : 몰래 빠져나오기

👉 내가 열었던 터미널이 유지되어, container 동작 유지

2️⃣ Ctrl + d : 내부 프로세스를 유지하지 않고 나옴

👉foreground로 동작하는 프로세스가 없기 때문에, 컨테이너는 중지 상태

 

 

 

실습 - 01

문제

 myhttpd라는 이름을 갖는 컨테이너를 띄워보세요. 이 컨테이너를 백그라운드로 실행시키고, 컨테이너 이미지는 httpd:latest 이걸로 하세요.
-d 옵션 사용, 베이스 이미지 : httpd:latest

 풀이

# 컨테이너 생성
root@ubuntu-tem:~# docker run -d --name myhttpd httpd:latest
Unable to find image 'httpd:latest' locally
latest: Pulling from library/httpd
7cf63256a31a: Already exists 
d2f10b557009: Pull complete 
4f4fb700ef54: Pull complete 
38fd0d422c41: Pull complete 
470035b3d48f: Pull complete 
fdebd6c6e1b2: Pull complete 
Digest: sha256:10381816bb7e60ae3a9db3784f2966a8910b6ff07c4da54bd2d62d2671c8ab6e
Status: Downloaded newer image for httpd:latest
e11dc0a7f7dc319da1db3df06540386e44824807331350f95d8cd795831c41d9

# 백그라운드에서 실행 확인
root@ubuntu-tem:~# docker ps
CONTAINER ID   IMAGE          COMMAND              CREATED          STATUS         PORTS     NAMES
e11dc0a7f7dc   httpd:latest   "httpd-foreground"   10 seconds ago   Up 9 seconds   80/tcp    myhttpd

 

실습 - 02

문제

실습 - 01의 컨테이너  ip를 조회해서 curl을 해보세요.

풀이

# myhttpd의 IP 정보 확인
root@ubuntu-tem:~# docker inspect myhttpd | grep -i IP
            "IpcMode": "private",
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
                    "IPAMConfig": null,
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,

# myhttpd 주소 접속
root@ubuntu-tem:~# curl 172.17.0.2
<html><body><h1>It works!</h1></body></html>

 

✅ test라는 컨테이너는 실행(run)되면서 bash라는 명령이 수행됨
➡️ 해당 명령만으로는 내부의 httpd 프로세스가 정상적으로 동작하지 않음

 

➡️ httpd-foreground : httpd:latest라는 컨테이너를 foreground로 유지시키기 위한 명령어로, 외부에서 httpd에 접속 가능

 

더보기

15. 동작 중인 컨테이너 접속 - exec

  • 내부로 진입해서 명령을 치겠음 = 콘솔 접속하는 느낌
# 이미 동작중인 컨테이너에 접속
root@ubuntu-tem:~# docker exec -it test bash
root@7d8596b029ec:/usr/local/apache2# ls
bin  build  cgi-bin  conf  error  htdocs  icons  include  logs	modules
root@7d8596b029ec:/usr/local/apache2# cd htdocs
root@7d8596b029ec:/usr/local/apache2/htdocs# ls
index.html
root@7d8596b029ec:/usr/local/apache2/htdocs# pwd 
/usr/local/apache2/htdocs

# httpd라는 컨테이너 이미지의 웹 루트 디렉토리 : /usr/local/apache2/htdoc
root@7d8596b029ec:/usr/local/apache2/htdocs# cat index.html
<html><body><h1>It works!</h1></body></html>

 

실습 - 03

문제

httpd:latest 이미지로 이름이 index_http 라는 컨테이너를 만들고 이 컨테이너의 주소로 curl 했을 때, hello라는 기본 페이지가 보이도록 해보세요.

풀이

더보기

방법 - 1️⃣

root@ubuntu-tem:~# docker run -d --name index_http1 httpd:latest
496446f5a1b6d33cdae7009d436473c62b44f30106d35c0d0c840ee6afed9485
root@ubuntu-tem:~# docker inspect index_http1 | grep -i ipa
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.3",
                    "IPAMConfig": null,
                    "IPAddress": "172.17.0.3",
root@ubuntu-tem:~# curl 172.17.0.3
<html><body><h1>It works!</h1></body></html>

root@ubuntu-tem:~# docker exec -it index_http1 bash
root@496446f5a1b6:/usr/local/apache2# cd htdocs
root@496446f5a1b6:/usr/local/apache2/htdocs# echo hello > index.html

root@ubuntu-tem:~# curl 172.17.0.3
hello

 

방법 - 2️⃣

  • 특문이 없었으면 명령을 그래로 수행해도 되는데, 특문이 있었기 때문에 sh -c를 통해 내가 수행할 명령어를 묶어줌
root@ubuntu-tem:~# docker exec index_http1 sh -c 'echo hello2 > /usr/local/apache2/htdocs/index.html'
root@ubuntu-tem:~# curl 172.17.0.3
hello2

 

실습 - 04

문제

nginx:latest 이미지로 이름이 index_nginx 라는 컨테이너를 만들고 이 컨테이너의 주소로 curl 했을 때 hello_nginx라는 기본페이지가 보이도록 해보세요. 웹루트디렉터리는 검색해 보세요!

풀이

더보기

방법 1️⃣

# 컨테이너 생성
root@ubuntu-tem:~# docker run -d --name index_nginx nginx:latest
1391b1e058ad30415ee321b70c6fd9d4330484ade6f66f8df110888b80e27170

# 컨테이너 콘솔 접속
root@ubuntu-tem:~# docker exec -it index_nginx bash
root@1391b1e058ad:/# ls
bin   dev		   docker-entrypoint.sh  home  lib64  mnt  proc  run   srv  tmp  var
boot  docker-entrypoint.d  etc			 lib   media  opt  root  sbin  sys  usr

# nginx 웹 루트 디렉토리 이동
root@1391b1e058ad:/# cd /usr/share/nginx/html
root@1391b1e058ad:/usr/share/nginx/html# ls
50x.html  index.html

# index.html 수정
root@1391b1e058ad:/usr/share/nginx/html# echo hello_nginx > index.html
root@1391b1e058ad:/usr/share/nginx/html# curl localhost
hello_nginx

결과 확인

 

방법 2️⃣ 

root@ubuntu-tem:~# docker exec index_nginx sh -c 'echo hello_nginx2 >  /usr/share/nginx/html/index.html'
root@ubuntu-tem:~# curl 172.17.0.2
hello_nginx2

 

더보기

16. 모든 컨테이너의 ID 확인

root@ubuntu-tem:~# docker ps -a -q
1391b1e058ad

 

17. 모든 컨테이너 삭제

root@ubuntu-tem:~# docker rm -f $(docker ps -qa)
1391b1e058ad

 

 Docker 옵션 - Volume(-v)🌟

  • 컨테이너와 호스트를 마운트 하는 개념
  • 컨테이너의 경우, 컨테이너가 삭제되면 내부에 데이터나 로그 같은 것들도 같이 삭제
    ➡️ 데이터베이스 컨테이너가 날아가면, 데이터도 다 날아가게 됨
    👉 영구적으로 저장시키고 싶은 데이터가 있다면,  -v(volume)을 통해 host에 영구 저장시킬 수 있음
더보기

1. 원본 경로 생성

root@ubuntu-tem:~# mkdir /host-txt

 

2. 컨테이너 생성

root@ubuntu-tem:~# docker run -d --name vol_nginx -v /host-txt:/txt nginx:latest
f38bb78a0d51b9b93bc97ed7ceeb37b08a87cc59dd01498437c103fc7db253e3

 

3. test.txt 파일 생성

root@ubuntu-tem:~# echo vol-test > /host-txt/test.txt
root@ubuntu-tem:~# cat /host-txt/test.txt
vol-test

 

4. 컨테이너 내부의 /txt 경로에 test.txt 파일이 있는 것을 확인 가능

 

5. 내부에서 삭제 ➡️ 외부에서도 삭제

 

 💡호스트 및 컨테이너 내부에 디렉토리가 없으면 자동으로 생성됨

root@ubuntu-tem:~# docker run -d --name vol_nginx -v /host-txt1:/txt nginx:latest
fc36ae23d0f6b922f4373e0648348417e271942327032456ad6f94c3391a4094
root@ubuntu-tem:~# ls /
bin   dev  home      host-txt1  lib32  libx32      media  opt   root  sbin  srv       sys  usr
boot  etc  host-txt  lib        lib64  lost+found  mnt    proc  run   snap  swap.img  tmp  var
root@ubuntu-tem:~#

 

실습 - 05

문제

-it 옵션이나 exec를  사용하지 않고,  nginx:latest 이미지로 컨테이너를 생성했을 때, vol_test라는 문구가 뜨도록 해보세요.

풀이

더보기

1. 기존 경로에 index.html 생성

root@ubuntu-tem:~# cd /host-txt
root@ubuntu-tem:/host-txt# ls
root@ubuntu-tem:/host-txt# echo vol_test > index.html

 

2. 컨테이너 생성 

root@ubuntu-tem:/host-txt# docker run -d --name my_nginx -v /host-txt:/usr/share/nginx/html nginx:latest
8691381e60260151fe499b995f17f8266c9c34ab59c77025b027a1a675ea65d4

root@ubuntu-tem:/host-txt# docker inspect my_nginx | grep -i ipa
            "SecondaryIPAddresses": null,
            "IPAddress": "172.17.0.2",
                    "IPAMConfig": null,
                    "IPAddress": "172.17.0.2",

 

3. 결과 확인

 

❗새로운 컨테이너를 띄워서 내부로 진입하여,  /usr/share/nginx/html로 가보니, 이미 index.html이 존재
 ➡️ 기존에 파일이 존재하면, 호스트의 파일이 우선순위가 높음

# 1️⃣ 새로운 컨테이너 생성
root@ubuntu-tem:/host-txt# docker run -it --name test nginx:latest bash

# 2️⃣ 웹 디렉토리 index.html 확인
root@cdbca1427ef6:/# cd /usr/share/nginx/html
root@cdbca1427ef6:/usr/share/nginx/html# ls
50x.html  index.html

👉 /usr/share/nignx/html이 바라보고 있는 경로가 달라짐  ➡️ /host-txt 마운트가 우선순위가 높음

 

Docker 옵션 - Publish(-p)🌟

  • 컨테이너를 외부에 노출/배포(publish)시키는 옵션
  • Destination NAT와 비슷한 개념
더보기

1. 컨테이너 생성 : Publish 옵션 설정

  • pub이라는 80포트이기 때문에, 컨테이너가 특정이 됨
# -p : publish
# 8080:80 ➡️ 호스트의 포트:컨테이너의 포트
root@ubuntu-tem:/host-txt# docker run -d --name pub -p 8080:80 nginx:latest

 

2. publish 확인

  • 0.0.0.0 호스트의 전체 대역에서 8080으로 들어오면 80으로 연결해줘라
  • 80/tcp ➡️ 컨테이너 내부 동작하는 프로세스가 서비스를 제공하는 포트
  • 일반적으로 웹서버는 80, python 장고는 8000, nodejs 기반은 3000번 등...
    ➡️ 중요한건 컨테이너 내부에서 실제로 어떤포트로 서비스가 제공되는지가 제일 중요하고,
    👉 그 포트를 찾아서 publish를 해줘야한다.
  • 호스트에서 컨테이너가 8080포트를 점유하고 있는 것을 확인 가능
    ➡️ 8080로 서비스를 제공함을 확인 가능

 

❗실습, 테스트할 때는 되도록이면 호스트의 well-known 포트는 사용하지 않는 것이 좋음

 ➡️ 최종적으로 웹서버를 배포하는 거면 80 포트 같은 well-known 포트를 사용

 

실습 - 06

문제

호스트의 /host_vol 이라는 경로에는 간단한 강아지 템플릿이 존재한다. 이 무료템플릿을 호스트의 7979번 포트로 publish 해보세요.

풀이

더보기

1. 마운트 경로 생성

# host_vol 마운트 경로 생성
root@ubuntu-tem:/# mkdir /host_vol
root@ubuntu-tem:/# cd host_vol

 

2. 무료 템플릿 설정

# dog 템플릿 다운로드
root@ubuntu-tem:/host_vol# wget https://www.free-css.com/assets/files/free-css-templates/download/page21/dogs-palace.zip

# unzip 패키지 다운로드
root@ubuntu-tem:/host_vol# apt install -y unzip

# dog 템플릿 압축 해제
root@ubuntu-tem:/host_vol# unzip dogs-palace.zip 

# zip 파일 삭제
root@ubuntu-tem:/host_vol# rm -rf dogs-palace.zip 

# 폴더명 변경
root@ubuntu-tem:/host_vol# mv dogs-palace dog

 

3. 컨테이너 생성

# 컨테이너 생성
root@ubuntu-tem:/host_vol# docker run -d --name pub_dog -v /host_vol/dog:/usr/share/nginx/html -p 7979:80 nginx:latest
3c1e55d6f27003c9075430147772fcc3ac40d738a432c7d7b80abe4ddae2ff88

 

4. 서비스 제공 확인 

# 서비스 제공 확인
root@ubuntu-tem:/host_vol# ss -tnlp
State       Recv-Q      Send-Q           Local Address:Port             Peer Address:Port      Process                                                                                        
LISTEN      0           4096             127.0.0.53%lo:53                    0.0.0.0:*          users:(("systemd-resolve",pid=823,fd=13))                                                     
LISTEN      0           128                    0.0.0.0:22                    0.0.0.0:*          users:(("sshd",pid=895,fd=3))                                                                 
LISTEN      0           128                  127.0.0.1:6010                  0.0.0.0:*          users:(("sshd",pid=17356,fd=10))                                                              
LISTEN      0           128                  127.0.0.1:6011                  0.0.0.0:*          users:(("sshd",pid=6201,fd=10))                                                               
LISTEN      0           4096                   0.0.0.0:7979                  0.0.0.0:*          users:(("docker-proxy",pid=21287,fd=7))                                                       
LISTEN      0           4096                   0.0.0.0:8080                  0.0.0.0:*          users:(("docker-proxy",pid=19819,fd=7))                                                       
LISTEN      0           128                       [::]:22                       [::]:*          users:(("sshd",pid=895,fd=4))                                                                 
LISTEN      0           128                      [::1]:6010                     [::]:*          users:(("sshd",pid=17356,fd=9))                                                               
LISTEN      0           128                      [::1]:6011                     [::]:*          users:(("sshd",pid=6201,fd=9))                                                                
LISTEN      0           4096                      [::]:7979                     [::]:*          users:(("docker-proxy",pid=21293,fd=7))                                                       
LISTEN      0           4096                      [::]:8080                     [::]:*          users:(("docker-proxy",pid=19824,fd=7))

 

Docker 옵션 - CP

더보기

1. host ➡️ 컨테이너(pub_dog)로 파일 복사

root@ubuntu-tem:/host_vol# echo cptest > cptest.txt
root@ubuntu-tem:/host_vol# ls
cptest.txt  dog

# pub_dog(컨테이너)의 최상위 경로에 cptest.txt 파일 복사
root@ubuntu-tem:/host_vol# docker cp ./cptest.txt pub_dog:/
Successfully copied 2.05kB to pub_dog:/
  • cptest.txt 복사 확인

 

2. 컨테이너(pub_dog)  ➡️ host로 파일 복사

root@ubuntu-tem:~# docker cp pub_dog:/cptest.txt ./
Successfully copied 2.05kB to /root/./
root@ubuntu-tem:~# ls 
cptest.txt  get-docker.sh  snap

 

Docker 옵션 - 환경변수 지정(-e)

  • 주로 데이터베이스 컨테이너 생성 시, 자주 사용됨
     ➡️데이터베이스 컨테이너의 경우엔 적어도 root 패스워드를 설정해야 컨테이너가 잘 동작함
더보기

1. 컨테이너 생성

root@ubuntu-tem:~# docker run -d --name envcon -e ENVTEST=test nginx:latest
42c3ee37af352286e8288e4f83d6faa7e23d7b844ea3cf61cebec527b1d9e15c
  • 컨테이너 생성시, -it로 만들면 나중에 나올때, 컨테이너가 잘 동작할지 장담하지 못함
     ➡️되도록이면 -d(detach)로 접속 권장

 

2. 컨테이너 접속

root@ubuntu-tem:~# docker exec -it envcon bash
root@42c3ee37af35:/#

 

3. 환경변수 확인

root@42c3ee37af35:/# echo $ENVTEST
test

 

Docker 옵션 - 작업 디렉토리 지정(-w)

  • 나중에 중요함
더보기

 1. 컨테이너 생성

root@ubuntu-tem:~# docker run -d --name workdir nginx:latest
367cc62182939fa2d8f8f8434be782ccc86f70eb4be12157750f345c2c1a6556

 

2. workdir 컨테이너 접속

  • 컨테이너 접속 경로 = 현재 작업 디렉토리
root@ubuntu-tem:~# docker exec -it workdir bash
root@367cc6218293:/#

 

3. 작업 디렉토리 지정하여 생성한 컨테이너

root@ubuntu-tem:~# docker run -d --name workdir1 -w /usr nginx:latest
bcc4f75231f0a80deed0d0cbb20922b8a03a5a9006bbaa52dbc5af8196200a7a

 

4. workdir1 컨테이너 접속

root@ubuntu-tem:~# docker exec -it workdir1 bash
root@bcc4f75231f0:/usr#

 

Docker 옵션 - 재시작(--restart)

더보기

1. docker engine 재시작 시, 동작 중이던 컨테이너 전부 stop

 

2. 컨테이너 생성 : 재시작 옵션

root@ubuntu-tem:~# docker run -d --name retest --restart=always nginx:latest
de4c52d08b023b37f5a671716d2f1aa3c18b0c49cbd189cd10a46721c3cc56a0

 

3. docker engine 재시작해도 컨테이너 재시작됨