Data science/MLOps

[5분 컷 이해] Docker 설치 및 사용, Dockerfile, Docker image 설명

연금(Pension)술사 2022. 6. 22. 20:41



요약


Docker을 이해하기위해서는 아래의 도커관련된 개념들의 이해가 필요하다.



* 도커이미지?
도커 이미지는 도커에서 필요한 서버 프로그램 + 소스코드 + 실행 파일로, 프로그램을 구동하기위한 종합선물세트이다.
추가적인 설치등이 필요없게 하나의 포장으로 엮어놓은 패키징된 파일을 의미한다.
예를 들어, 스타크레프트 2를 베틀넷클라이언트로 설치할 수 있지만, 윈도우 + 베틀넷클라이언트로 이미 깔린 코드 + 그레픽카드 드라이버 등을 한 번에 포장해서 도커이미지로 만들어놓으면,
똑같은 시스템을 가진 사람이 도커이미지로



* 도커 컨테이너(Docker container) ?
이미지를 실행한 상태를 의미. 패키징된 도커이미지를 격리된 동간에서 동작시키는 것(기술)을 의미한다.


* 이미지(Image)와 레이어(layer)?

 

Docker 설치


다음의 URL에서 "Docker Desktop for Windows"을 클릭. (URL: https://docs.docker.com/desktop/windows/install/)

Click Click만 하면 된다. 필요하다면 WSL을 설치해야한다는데, 다음의 과정을 진행하면된다.

1. 관리자권한으로 Powershell.exe을 켠다.

2. 아래의 코드를 하나하나 붙여넣는다. 중간에 "https"으로 시작하는 주소의 wsl도 설치가 필요하다.

dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart

# https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi < 주소 복사해서 설치한다.

wsl --set-default-version 2

 

3. 아래와 같이 Docker Desktop이 설치가 가능하다.

 

 

 

Docker로 linux container 실행하기


처음에 docker을 설치하고, docker에 있는 이미지를 아래와 같이 검색할 수 있다. 하지만 설치되어있는 이미지가 하나도 없기에 출력결과는 아무것도 없다.

docker images
# 아무것도 출력이 안됨

 

 

다음과 같이, Docker Hub에서 이미지를 검색할 수 있다. 이 공간(Docker Hub)은 공개된 공간으로 여러 이미지들이 공유되고, 개발자들이 다운로드 받을 수 있다. 

docker search ubuntu

 

 

아래와 같이, Docker Hub에서 "ubuntu"이미지를 검색해보자. 아래와 같이 여러 출력결과 들이 나오는데, 별(STARS, 일종의 "좋아요")이 가장 많고, OFFICIAL인 이미지를 하나 다운로드(PULL)해서 설치해본다.

# docker pull [옵션] [경로]<이미지명>[:테그명]
docker pull ubuntu

 

 

Docker 내에 제대로 이미지가 다운로드(PULL)되었는지 확인해보자. Docker 이미지가 검색이 되어야하므로 'docker image'라는 명령어로 설치된 이미지를 검색한다. 아래와 같이 1개의 리포지토리명이 ubuntu인 이미지가 설치된다.

docker images

# 출력
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    27941809078c   2 weeks ago   77.8MB

 

 

이제 도커이미지는 빌드되어있는 것을 컨테이너로 띄우기만하면 된다. 도커 컨테이너에서 아래와 같은 명령어로 실행시킬 수 있다. 아래의 명령어의 해석은 다음과 같다.

  • -d 옵션: 이미지로부터 도커 컨테이너를 띄울 때, 백그라운드에서 돌 수 있도록 실행하여라. 이는 예를 들어, youtube뮤직을 틀어 놓고 다른작업을 하기위한 것과 동일하다. 흔히 이것을 detach모드로 실행시킨다고도 한다.
  • --name <container 명>: 도커 컨테이너를 실행할 때, 지정할 이름을 넣는다. 아래의 예시는 "my_ubuntu"로 실행하였다.
  • -i : 상호 입출력
  • -t : bash 쉘을 사용할수있도록함
docker run -dit --name my_ubuntu ubuntu

# 출력
74a92f6f04354520d3709d370bf1dabbc12aaf432225001eb6a2a96feaaa7d12

 

 

우분투 컨테이너가 제대로 설치되어있는지 다음의 명령어로 확인해보자.

docker ps

# 출력
CONTAINER ID   IMAGE     COMMAND   CREATED          STATUS          PORTS     NAMES
74a92f6f0435   ubuntu    "bash"    14 seconds ago   Up 13 seconds             my_ubuntu

 

 

컨테이너에 아래와 같이 접속이 가능하다.

# CONTAINER ID을 이용한 접속
docker attach 74a92f6f0435

# CONTAINER NAME을 이용한 접속
docker attach my_ubuntu

 

 

컨테이너에서 도커 컨테이너 종료없이 나오고 싶을 때는 키보드에서 아래의 자판을 연달아 누른다. 철권에서 케릭터 커멘드 누르듯 연달아서 다음을 눌러준다. "CTRL+P"->"CTRL + Q" (=deteching without stopping).

# 키보드에서 CTRL+P -> CTRL+Q
root@d70fbbd0ee4b:/# read escape sequence

 

 

혹시, 도커가 사용이 중지되어서 다시 시작하고 싶다면, docker start을 하면된다. 

# 도커가 중지된 경우 docker ps -a로 확인가능 
# -a option: 프로세스 중인 모든 컨테이너(all)을 확인
docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED       STATUS                           PORTS     NAMES
d70fbbd0ee4b   ubuntu    "bash"    2 hours ago   Exited (137) About an hour ago             my_ubuntu


# 도커 시작 (ID로)
docker start d70fbbd0ee4b  # 또는

# 도커 시작 (name으로)
docker start my_ubuntu

 

 

 

도커이미지 빌딩을 위한 Dockerfile 작성법


 

 

도커 컨테이너는 도커 이미지가 실제 구동되는 것을 의미하고, 하나의 도커 이미지로 어려 도커컨테이너를 실행시킬 수 있다. 비유하자면, 도커 컨테이너가 밀키트 만드는 제조법으로 끓여낸 부대찌게라면, 도커이미지는 밀키트 제조 레시피 및 재료이다. 위에서는 도커이미지를 도커허브(Docker Hub)에서 다운로드받아서 사용했고, 이를 이용해서 도커 컨테이너를 구동하였다. 그렇다면, 도커이미지를 만들기 위해서는 어떤 것들이 필요한가? 이 정답은  Dockerfile이다. Dockerfile은 도커이미지를 만들기 위한 레시피를 의미한다. 이 레시피에는 어떤 파일들을 참조하고있는지, 어떤 과정이 진행되는지 파악할 수 있다.

 

 

 

 

Dockerfile 에서 사용되는 명령어의 모음

아래와 같이 도커파일로부터 이미지를 만들 때 쓸 수 있는 명령어는 다음과 같다. 주의할 것은 RUN은 이미지를 만들 때 실행되는 코드이며, ENTRYPOINT, CMD은 컨테이너를 만들고나서 실행되는 코드이다.

 

명령어 기능 예시
FROM 새로운 이미지를 생성할 때, 기반으로 상용할 이미지를 지정. 주로 OS을 지정한다. 버전까지 지정해주는 것이 좋다. (어짜피 버전까지 지정해서 패키징해야, 플렛폼 독립적으로 쓸 거니깐).

Dockerfile은 반드시 FROM 구문으로 시작해야한다. 이미지가 내 로컬 docker 이미지가 없어도 손쉽게 퍼블릭 리포지토리에서 가져올 수 있다.
FROM ubuntu:18.04

ENV
환경변수를 할당하고 싶을 때 사용 ENV PROJECT_DIR MY_DIR

: 도커이미지을 만들 때, PROJECT_DIR 환경변수에는 MY_DIR을 할당하라는 명령어
WORKDIR shell의 cd 명령문처럼 컨테이너 상에서 작업 디렉토리로 전환을 위해 사용됨  
COPY . 호스트 컴퓨터에 있는 디렉터리나 파일을 Docker이미지 내부로 복사하기위해 사용된다. 도커 컨테이너는 격리된 공간에서 패키징된 이미지를 실행한다고 했기에 별도의 호스트컴퓨터(진짜 물리적인 컴퓨터)내에 있는 자료를
가져오기위해서는 별도의 명령어가 필요하다. 이 명령어가 COPY 명령어이다
COPY ~/model ./model
RUN Dockerfile로부터 도커이미지를 빌드하는 순간에 실행된다. 
* RUN명령어는 실행시마다 레이어가 생생되고 케시된다.

* RUN은 이미지를 만들 때 생성되는 명령어이다.
RUN apt-get update
ENTRYPOINT ENTRYPOINT은 컨테이너 생성 후, 최초로 실행되는 명령어이다.  
CMD CMD도 컨테이너 생성후에 실행되는 명령어이다 (실행이 안될 수도 있다).

docker run <image-name> [CMD]의 명령어에서 CMD가 없는 경우에 디폴트로 돌리기 위함이거나, 인자를 받기위함으로 사용된다.

docker run 뒤에 CMD가 없으면 default로 실행, 다른명령어가 있으면 실행이 안됨
 

 

 

FROM 명령어: 아래와 같이 dockerfile을 하나 작성하고, ubuntu:18.04을 작성한다. 왠만하면 버전명까지 넣어준다. docker build -t [이미지명]으로 도커이미지를 빌딩한다.

# vim을 이용하여 dockerfile을 작성
vim dockerfile


# vim 내 내용
FROM ubuntu:18.04

# vim을 빠져나옴
$ docker build -t my_ubuntu:first .

# 출력
[+] Building 1.3s (5/5) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 31B                                                                                0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/ubuntu:18.04                                                    1.2s
 => CACHED [1/1] FROM docker.io/library/ubuntu:18.04@sha256:478caf1bec1afd54a58435ec681c8755883b7eb843a8630091890  0.0s
 => exporting to image                                                                                             0.0s
 => => exporting layers                                                                                            0.0s
 => => writing image sha256:d513fc32a2db453cb336aae40870e42a81451570aadbdc25e1662fb07dcfb1b0

 

 

도커 이미지 빌딩 결과는 다음과 같다. 아래와같이 도커리포지토리 이름은 my_ubuntu이며 ":first"으로 적어주었던부분은 TAG란에 들어갔다. 실제로는 TAG란에는 주로 버전명을 기입해서 소프트웨어의 버전관리를 용이하게 할 수 있다.

$ docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    27941809078c   2 weeks ago   77.8MB
my_ubuntu    first     d513fc32a2db   2 weeks ago   63.1MB

 

 

도커 RUN은 연속해서 실행할 때 마다 새로운 레이어가 생성이 된다. 예를 들어 RUN을 두번 실행되면, FROM으로 생성된 이미지 -> 컨테이너로 생성 -> 첫 번째 RUN을 실행하여 얻은 이미지 -> 첫 번째 RUN을 실행하여 얻은 이미지에서 컨테이너를 만듬 -> 이 컨테이너에서 두 번째 RUN을 실행 -> 이 내용을 이미지로 저장. 아래와같이 dockerfile을 하나 생성하고 이미지 빌딩과정을 하나 추적해보자.

 

 

 

 

 



이제 dockerfile을 하나 작성하여 docker image을 하나 생성해보자. 아래의 dockfile을 이용해서 빌딩된 도커이미지의 로그를 아래와 같이 이해할 수 있다.먼저 FROM 에 적인 ubuntu:18.04가 docker이미지에 없기에 docker.io에서부터 다운로드받아온다. 그다음에 캐시를 해놓는다.캐시해놓은 이미지로 다시 컨테이너를 띄우고, 그 후 RUN apt-get-y udpate을 한다. 그 후에 다시 이미지 캐시하고 다시 컨테이너를 띄우고 마지막 RUN apt-get -y install curl을 실행한다. 마지막에 RUN apt-get -y install curl까지 완료되면 해당 이미지를 내뱉는다. 

# dockerfile
FROM ubuntu:18.04
RUN apt-get -y update
RUN apt-get -y install curl

# docker image build
docker build -t my_ubuntu:v1.0 .

# 출력
 docker build -t my_ubuntu:v1.0 .
[+] Building 49.9s (7/7) FINISHED
 => [internal] load build definition from Dockerfile                                                               0.0s
 => => transferring dockerfile: 108B                                                                               0.0s
 => [internal] load .dockerignore                                                                                  0.0s
 => => transferring context: 2B                                                                                    0.0s
 => [internal] load metadata for docker.io/library/ubuntu:18.04                                                    1.5s
 => CACHED [1/3] FROM docker.io/library/ubuntu:18.04@sha256:478caf1bec1afd54a58435ec681c8755883b7eb843a8630091890  0.0s
 => [2/3] RUN apt-get -y update                                                                                   21.1s
 => [3/3] RUN apt-get -y install curl                                                                             26.9s
 => exporting to image                                                                                             0.2s
 => => exporting layers                                                                                            0.2s
 => => writing image sha256:a6d72fef1af26555d21b78e4ca5e985bfa82df9dfcd6c8d37dd69d0178e93a32



아래와 같이 docker buil을 실행하면 처음에 Ubuntu 18.04을 베이스로하는 Container을 띄우고, 그 위에 layer 1. layer 2을 쌓아 최종 image을 만든다. 그렇게 만든 이미지는 추가적으로 변경할 수 없고 READ ONLY상태이다. 이를 container로 비로서 띄워야만 컨테이너 내부에서 파일도 쓰고 읽고 할 수 있다. 

 

 

Docker layer의 개념 도식화




생성된 도커 이미지는 아래와 같이 삭제할 수 있다.

$ docker images
# 출력
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
my_ubuntu    v1.0      a6d72fef1af2   9 minutes ago   119MB
ubuntu       latest    27941809078c   2 weeks ago     77.8MB


$ docker rmi a6d72fef1af2
# 출력
Untagged: my_ubuntu:v1.0
Deleted: sha256:a6d72fef1af26555d21b78e4ca5e985bfa82df9dfcd6c8d37dd69d0178e93a32

 

 

 

반응형