Docker

[Docker] 도커 이미지 / 컨테이너 생성 및 접근

sian han 2023. 1. 24. 23:48

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

 

※ 도커 이미지

  • 이미지는 컨테이너를 생성할 때 필요한 요소이다.
  • 이미지는 여러개의 계층으로 된 바이너리 파일로 존재한다. ( 바이너리 파일 : 데이터의 저장과 처리를 목적으로 0과 1의 이진 형식으로 인코딩된 파일) 
  • 컨테이너를 생성하고 실행할 때 읽기 전용으로 사용된다.

 

▷ 이미지 이름 기본형식

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

  • 저장소(Repository) : 이미지가 저장된 장소. 
  • 이미지 이름 : 이미지 이름 설정은 생략할 수 없다.
  • 태그 : 이미지의 버전관리에 사용한다. 일반적으로 버전 (=2.0) 을 명시하지만 태그를 생략하면 도커 엔진은 이미지의 태그를 latest 로 인식함

 

※ 도커 이미지 구조

이미지의 이름을 구성하는 저장소, 이미지 이름, 태그를 잘 관리하는 것 뿐만아니라

  • 이미지가 어떻게 생성되고 삭제되는지
  • 이미지의 구조는 어떻게 돼 있는지

등을 아는 것이 중요하다. 

 

도커는 기본적으로 도커허브라는 중앙 이미지 저장소에서 이미지를 내려받는다.

docker create
docker run
docker pull

위 명령어로 이미지를 내려받을 때 도커는 도커허브에서 해당 이미지를 검색한 뒤 내려받는다. 

 

 

 

▶ 도커 이미지 생성

도커로 개발할 때 대부분 컨테이너에 애플리케이션을 위한 특정 개발환경을 직접 구축한 뒤 사용자만의 이미지를 직접 생성해야 할 것 이다. 이를 위해 컨테이너 안에서 작업한 내용을 이미지로 만드는 방법은 다음과 같다.


▷ commit_test 컨테이너 생성

docker run -i -t --name commit_test ubuntu:14.04

 

 commit_test 컨테이너를 commit_test:first 라는 이름의 이미지로 생성

docker commit \
-a "sian00" \
-m "my first commit" \
commit_test \
commit_test:first

-a 옵션은 author 을 뜻하며, 이미지의 작성자를  나타내는 메타데이터를 이미지에 포함시킴

commit_test 라는 이름에 first 라는 태그로 이미지가 생성된 것을 확인할 수 있다. 

 

 

 

▶ 이미지 구조 이해

위와같이 컨테이너를 이미지로 만드는 작업은 commit 명령어로 쉽게 수행할 수 있다.

 

이미지의 자세한 정보 확인

docker inspect commit_test:first

 

가장 아래에 Layers를 보자.

"Layers": [
                "sha256:f2fa9f4cf8fd0a...",
                "sha256:30d3c4334a23797...",
                "sha256:83109fa660b2ed9...",
                "sha25...

기존 ubuntu:14.04 이미지에서 commit_test:first 라는 이름의 이미지를 생성했다.

이미지를 커밋할 때 컨테이너에서 변경된 사항만 새로운 레이어로 저장하고, 그 레이어를 포함해 새로운 이미지를 생성한다.

 

 

▶ 이미지 삭제하기

docker rmi commit_test:first

 

이미지를 사용중이 컨테이너가 존재해 삭제할 수 없다는 에러메세지가 출력되었을땐 ? 

컨테이너를 삭제한 후 이미지를 삭제하자

docker stop commit_test && docker rm commit_test
docker rmi commit_test:first

 

이미지를 삭제하라는 명령어를 던졌는데 다음과 같은 결과가 출력된다.

Untagged 는 무엇이고, Deleted 는 무엇일까 ?

 

Deleted 라는 출력결과는 이미지 레이어가 실제로 삭제됐음을 뜻한다. 

삭제되는 이미지의 부모 이미지가 존재하지 않아야만 해당 이미지의 파일이 실제로 삭제된다.

그렇지 않다면 실제 이미지 파일을 삭제하지 않고 레이어에 부여된 이름만 삭제한다.

Untagged 는 이미지에 부여된 이름만 삭제한다는 것을 뜻한다.

 

 

 

 

▶ 이미지 추출

이미지를 별도로 저장하거나 옮기는 등 이미지를 단일 바이너리 파일로 저장해야할 때 이미지를 추출한다.

 

save : 컨테이너의 커맨드, 이미지 이름과 태그 등 이미지의 모든 메타 데이터를 포함해 하나의 파일로 추출할 수 있다.

docker save
docker save -o ubuntu_14.04.tar ubuntu:14.04

-o : 추출될 파일명을 입력하는 옵션

 

 

이렇게 추출된 이미지는 load 명령어로 도터에 다시 로드할 수 있다. 완전히 동일한 이미지가 도커 엔진에 생성된다.

docker load -i ubuntu_14_04.tar

 

 

▶ 이미지 배포

생성한 이미지를 다른 도커 엔진에 배포하고 싶다면 ?

  •  save, export 를 사용해 이미지를 단일 파일로 추출 => 파일의 크기가 너무 크면 어려움이 있다.
  • 도커 허브 이미지 저장소 사용
  • Docker Private Registry 사용 > 사용자가 직접 이미지 저장소를 만든다.

도커허브는 도커 이미지를 저장하기 위한 클라우드 서비스로,

사용자는 이미지를 올리고(docker push), 내려받기(docker pull) 만 하면 되므로 쉽게 사용할 수 있다.

 

 


 

※ 도커 컨테이너

이미지로 컨테이너를 생성하면 독립된 공간이 생성되고, 이것을 도커 컨테이너라고 한다. 

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

 

 

▷ 컨테이너를 생성하고 실행

docker run

컨테이너를 생성하고 실행하는 역할을 함.

로컬에 존재하지 않는 이미지를 입력하면 중앙 이미지 저장소인 도커 허브에서 자동으로 이미지를 내려받는다.

run 명령어는 pull, create, start 명령어를 일괄적으로 실행한 후 attach 가 가능한 컨테이너라면 컨테이너 내부로 들어간다.

 

run 명령어를 실행하면서 지정한 이미지가 도커에 존재하지 않으면 이지를 pull 한다. 태그를 지정하지 않고 Pull 하면 도커 엔진이 latest 태그로 지정된 이미지를 pull 한다.

 

 

▷ 컨테이너를 생성, 실행하고 컨테이너 내부로 들어옴

docker run -i -t {이미지 이름}

-i : 상호 입출력

-t : tty 를 활성화하여 bash 셸을 사용하도록 설정함

=> 이 옵션들을 추가해 run 을 실행하면 표준 입출력이 활성화된, 상호작용이 가능한 셸 환경을 사용할 수 있다. 기본 이미지들을 컨테이너를 시작할 때 /bin/bash 를 COMMAND 로 설정해 실행함으로써 bash 셸을 쓸 수 있게 설정한다. 예를 들어 -i-t 옵션을 추가하여 mysql 컨테이너를 생성하면 하나의 터미널을 차지하는 mysqld 프로그램이 포그라운드로 실행된 로그를 볼 수 있다. 

 

■ 추가 옵션

-d : -i -t 가 컨테이너 내부로 진입하도록 attach 가능한 상태로 설정한다면 -d 는 Detached 모드로 컨테이너를 실행한다. Detached 모드는 컨테이너를 백그라운드에서 동작하는 애플리케이션으로써 실행하도록 설정한다. 

-i -t 와 달리 입출력이 없는 상태로 컨테이너를 실행한다. Detached 모드인 컨테이너는 반드시 컨테이너에서 프로그램이 실행되어야한다. docker start로 컨테이너를 시작해도 컨테이너 내부에 터미널을 차지하는 포그라운드로써 동작하는 프로그램이 없으므로 컨체이너는 시작되지 않는다. 

 

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

-e MYSQL_ROOT_PASSWORD=password

컨테이너의 MYSQL_ROOT_PASSWORD 환경 변수의 값을 password 로 설정하는다는 의미이다. 

설정한 환경변수를 확인해보려면 ? => echo 명령어를 통해 출력해보면 된다.

# echo ${ENVIRONMENT_NAME}

-d 옵션을 사용해 생성된 컨테이너는 입출력을 위한 셸을 사용할 수 없다.

 

=> exec 명령어를 사용한다

exec 명령어를 사용하면 컨테이너 내부에서 명령어를 실행한 뒤 그 결과값을 반환받을 수 있다. 

# docker exec -i -t wordpressdb /bin/bash

 

-i -t 옵션을 추가하지 않고 단순히 exec 만 쓰면 컨테이너 내부에서 실행한 명령어에 대한 결과만 반환한다.

 

 

--link : 컨테이너에서 컨테이너로 접근할 때 별명(alias) 로 접근하도록 설정한다.

 

 

▷ 컨테이너 생성

docker create

 

create 명령어는 이미지를 pull 한 후 컨테이너를 생성만 할 뿐 컨테이너 내부로 들어가지 않음

 

docker create -i -t --name siantest testimage:1

testimage:1 이미지로 siantest 라는 이름을 가진 컨테이너 생성

 

 

▷ 컨테이너 정지 / 호스트 도커환경으로 돌아옴

exit

bash 셸을 종료함으로써 컨테이너를 정지하고 컨테이너 내부에서 호스트의 도커환경으로 돌아오기. 

 

▷ 컨테이너 내부에서 빠져나옴

Ctrl+D

컨테이너 내부에서 빠져나오면서 동시에 컨테이너를 정지시킴

 

Ctrl+P,Q

 컨테이너를 정지하지 않고 컨테이너 내부에서 빠져나옴

 

 

▷ 이미지 내려받기

docker pull

 

▷ 도커 엔진에 존재하는 이미지 목록 확인

docker images

 

▷ 컨테이너를 시작함

docker start

 

▷ 컨테이너 내부로 들어감

docker attach dd0 // ID : ddO4332kadsf

 

위와 같이 컨테이너를 대상으로 하는 모든 명령어는 컨테이너 이름 대신 ID 를 사용할 수 있다. ID 는 앞의 2~3 글자만 입력해도 된다.

 

 

▷ 컨테이너 목록 확인

docker ps

 

정지되지 않은 컨테이너만 출력한다.

 

docker ps -a

정지된 컨테이너를 포함한 모든 컨테이너를 출력한다.

 

docker ps -a -q

정지된 컨테이너를 포함한 모든 컨테이너의 ID 만 출력한다

 

컨테이너의 상태는 STATUS 에서 확인 가능하다.

  • Exited : 정지된 상태
  • Up...seconds : 실행중인  상태
  • Pause : 일시중지된 사이
  • CONTAINER ID : 컨테이너에 자동으로 할당됨. docker inspect 명령어를 통해 전체 ID 확인 가능
  • IMAGE : 이미지를 생성할 때 사용된 이미지 이름
  • COMMAND : 컨테이너가 시작될 때 실행될 명령어. 이미지에 내장된 command 는 docker run 이나 create 명령어의 맨 끝에 입력해서 컨테이너를 생성할 때 덮어쓸 수 있다. ex ) /bin/bash => 컨테이너가 실행될 때 상호 입출력이 가능한 셸 환경을 사용할 수 있게 됨
  • CREATED : 컨테이너가 생성되고 난 뒤 흐른 시간
  • STATUS : 컨테이너의 상태를 나타낸다. 
  • PORTS : 컨테이너가 개방한 포트와 호스트에 연결한 포트를 나열한다. 컨테이너를 생성할 때 외부에 노출하도록 설정하지 않았다면 PORTS 항목에는 아무것도 출력되지 않는다. 
  • NAMES : 컨테이너의 고유한 이름. 컨테이너를 생성할 때 --name 옵션으로 이름을 설정하지 않으면 도커 엔진이 임의로 형용사와 명사를 무작위로 조합해 이름을 설정한다. 

 

▷ 원하는 정보만 출력

docker ps --format

 

셸의 화면이 작아서 ps 명령어의 출력 결과가 줄바꿈되어 알아보기 힘들때는 --format 옵션에 {{.ID}}\t{{Status}} 와 같은 Go 템플릿을 입력해서 원하는 정보만 출력할 수 있다. 

docker ps --format "table {{ID}}\t{{Status}}\t{{.Image}}"

 

▷ 컨테이너 이름 변경

docker rename

 

▷ 컨테이너 삭제

docker rm

한번 삭제한 컨테이너의 복구는 불가하다. 신중하게 삭제 !

실행중인 컨테이너는 삭제할 수 없다. 컨테이너를 정지한 뒤 삭제하거나 -f 를 추가한다. 

 

 

▷ 컨테이너 중지

docker stop

 

▷ 전체 컨테이너 삭제

docker container prune

 

▷ 컨테이너 리스트를 변수로 사용해 중지하기

docker stop $(docker ps -a -q)

 

▷ 컨테이너 모든 구성단위의 정보 확인

docker inspect

컨테이너, 이미지, 볼륨 등 도커의 모든 구성 단위의 정보를 확인할 수 있다.

docker volume inspect
docker container inspect
docker inspect --type volume {볼륨 이름}

 


▶ 컨테이너를 외부에 노출

 

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

 

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

컨테이너 내부로 들어간 후 ifconfig

 

▷ 컨테이너를 생성하면서 외부에 노출

-p [호스트의 포트]:[컨테이너의 포트]

-p  옵션은 컨테이너의 포트를 호스트의 포트와 바인딩해 연결할 수 있게 설정한다.

ex 1. ) 호스트의 7777번 포트를 컨테이너의 80번 포트와 연결 => 7777:80

ex 2. ) 호스트의 특정 IP 를 사용하려면 => 192.168.0.100:7777:80 과 같이 바인딩할 IP 와 포트를 명시

 

-p 80 과 같이 입력하면 컨테이너의 80 번 포트를 호스트 포트 중 사용할 수 있는 포트와 연결한다. 그러나 정확히 호스트의 어느 포트와 연결되었는지 확인할 수 없으므로 docker ps 명령어를 입력해 PORTS 항목을 확인해야 한다.

아래 명령어로도 확인가능

docker port {컨테이너 명}

{} 컨테이너가 사용중인 호스트의 포트가 출력된 결과

: 0.0.0.0 은 호스트의 활용가능한 모든 네트워크 인터페이스에 바인딩함을 뜻한다.

 

 

■  포트포워딩

  • 호스트와 컨테이너 포트 연결
  • -p 옵션을 사용한다.

ex ) 아파치 웹서버 컨테이너를 생성하고 실행해보자

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

따라서 접근하기 위해 172.17.0.x:80 의 주소로 접근해야 한다. (80:81 과 같이 포트포워딩을 했다면 외부에서 웹서버에 접근할 수 없다.)

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

 

=> 웹 브라우저로 [호스트IP]:[호스트포트] 에 접근했을 때 아파치 웹서버를 볼 수있다.