JUINTINATION

도커(Docker) 가볍게 입문해보기 - 3 본문

StudyNote

도커(Docker) 가볍게 입문해보기 - 3

DEOKJAE KWON 2024. 1. 27. 00:05
반응형

지난 도커(Docker) 가볍게 입문해보기 - 2에서 이어지는 내용이며 해당 글은 이 링크로 들어가면 확인할 수 있다. 지난 글에서 언급했듯이 이 스터디는 학교 선배가 작성한 강의 자료를 참고하였으며 ETRI에서 대여한 관련 책과 추가로 대여한 다른 책을 참고했다.

 

GitHub - J-Hoplin/Docker-n-K8S-Lecture-Note: Docker,Kubernetes 강의자료

Docker,Kubernetes 강의자료. Contribute to J-Hoplin/Docker-n-K8S-Lecture-Note development by creating an account on GitHub.

github.com

docker commit & docker diff

docker commit 명령어는 컨테이너 변경사항을 이미지 파일로 생성하는 역할을 한다. 예를 들어 ubuntu 이미지에서 아래 과정을 수행한다고 가정하자.

  1. example-directory라는 디렉토리를 생성한다.
  2. example-directory에 test.sh라는 파일을 생성한다. 이 쉘 스크립트 파일은 'hello world'라는 문자열을 출력할 수 있어야 한다.
  3. 기본적인 ubuntu 패키지 매니저 update, upgrade를 진행한다.

이 과정을 commit-test 컨테이너에서 진행했는데 나는 지난번에 연습하면서 해당 컨테이너를 이미 만들었기 때문에 $ docker rm commit-test 커맨드를 실행하여 해당 컨테이너를 지우고 시작했으며 $ apt-get update & apt-get upgrade 명령어는 시간이 너무 오래 걸리기 때문에 생략했다.

이 상태에서 새 터미널 창을 열고(맥 os의 경우 command + n 를 통해 새 터미널 창을 열 수 있다.) 아래와 같이 docker diff (컨테이너 이름 혹은 id) 명령어를 실행하면 아래와 같이 로그들이 나오는 것을 볼 수 있다.

$ apt-get update & apt-get upgrade 커맨드까지 실행했으면 훨씬 많이 나왔을 것이다. 아무튼 $ docker diff commit-test 커맨드의 실행 결과를 보면 앞에 A라는 플래그가 있는것을 볼 수 있다. 이 과정에서는 나오지 않았지만 C, D라는 플래그도 존재한다. 이 플래그들은 사용한 도커이미지를 기준으로 변경사항들을 의미하며 각각의 플래그는 아래 의미를 가진다.

  • A : 추가된파일
  • C : 변경된파일
  • D : 삭제된 파일

이제 docker commit 을 사용해서 위 과정을 진행한 컨테이너를 이미지화 해볼것이다. docker commit의 기본 사용법은 아래와 같다.

docker commit <옵션> <컨테이너 이름 혹은 id> <이미지이름>:<태그, 생략시 latest로 치환>

commit 옵션 중 사용해볼 것은 -a와 -m 옵션이다.

  • -a : 커밋을 진행한 사람
  • -m : 커밋메세지

docker commit을 사용하기 위해 우선 컨테이너에서 나와 종료시킨다. 그 후 docker commit 명령어를 사용해준다. 이미지 생성시 태그가 있는 경우, 없는 경우 모두 생성해본 뒤 방금 전에 생성한 이미지를 grep 명령어를 사용해 출력해본다.

이후 $ docker run -it --name containerbycommit imagebycommit 커맨드를 실행하여 해당 컨테이너를 실행한다. 물론 나는 지난번에 연습하면서 해당 컨테이너를 이미 만들었기 때문에 $ docker rm containerbycommit 커맨드를 실행하여 해당 컨테이너를 지우고 시작했다. 이후 test.sh 의 내용을 sed 명령어를 이용하여 변경하고 확인해보자.

이후 다른(혹은 새로운) 터미널을 열고 docker diff 명령어를 사용하고 결과를 보면 아래와 같이 C 플래그와 함께 로그가 출력되는 것을 볼 수 있다.

$ rm test.sh 커맨드를 실행하여 test.sh 파일을 삭제한 후에 다른(혹은 새로운) 터미널을 열고 docker diff 명령어를 사용하고 결과를 보면 아래와 같이 D 플래그와 함께 로그가 출력되는 것을 볼 수 있다.

Dockerfile

만약 우분투에 git , gcc 가 설치된 상태의 이미지가 필요하다고 가정을 하자. 위에서 본 docker commit 명령어를 이용해서 컨테이너 자체를 이미지로 변경하는 방법이 생각났다면 이런 방법에서의 단점은 명확하다.

  1. 패키지 설치를 일일히 설치해야하며 이미지에 특정 코드를 불러와야하는 경우, 골치아프다.
  2. 만약 이미지를 실수로 삭제한다면 다시 컨테이너를 만들고 다시 이미지로 만드는 과정을 거쳐야한다. 그리고 혹시라도 많은 명령어를 사용하여 이미지를 만들었다면 그 명령어들을 모두 기억할 수 있는 확률도 매우 적을 것이다. 이 뿐만아니라 과정도 꽤 복잡하다.

이러한 단점을 해결해줄 수 있는 것이 바로 Dockerfile이다. Dockerfile 문법에 대해 알아보기 전에 전반적인 Dockerfile 흐름을 살펴보자.

간단하게 apache2를 설치하고, 웹페이지 하나를 호스팅 하는 실습을 진행해 볼 것이다. 자신이 실습하고자 하는 디렉토리에 Dockerfile 이라는 파일을 생성한다(확장자 없음). 참고로 소스코드는 dockerfile-scratch에 있다.

다음은 내가 작성한 Dockerfile이다.

FROM ubuntu
LABEL maintainer="juintination"
RUN apt-get update && apt-get upgrade -y && apt-get install vim git apache2 -y

COPY ./index.html /var/www/html/index.html
ADD ./foo.js /var/www/html/foo.js

WORKDIR /var/www/html
EXPOSE 80

CMD ["-D", "FOREGROUND"]
ENTRYPOINT ["apachectl"]

다음은 내가 작성한 실습용 foo.js와 index.html 파일이다. Dockerfile과 동일한 디렉토리에 있어야 한다.

// foo.js
const exampleAlert = () => {
    alert("example alert")
}

window.onload = () => {
    const element = document.getElementById('jsloading');
    element.innerText = "Javascript Loaded!"
}
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="./foo.js"></script>
    <title>Document</title>
</head>

<body>
    <h1>This webpage is hosted from docker container</h1>
    <p style="color: blue;">Dockerfile from scratch</p>
    <p id="jsloading">Wait for javascript loaded</p>
    <button onclick="exampleAlert()">Example Button</button>
</body>
</html>

Dockerfile을 이미지로 만들기 위해서는 docker build라는 명령어를 사용하게 된다. 사용 방식은 아래와 같다.

docker build (옵션) (Dockerfile경로)

대표적인 옵션으로는 -t, -f가 있다

  • -t : 이미지의 태그를 지정할때 사용한다.
    • 필수 권장 옵션이며 아래와 같이 사용자 명을 같이 기재할 수 있다.
    • Docker hub에 이미지를 올리기 위해서는 사용자 명을 꼭 붙여야한다.
docker build -t imagetag .
docker build -t hoplin/imagetag .
  • -f : 기본적으로 도커엔진은 지정한 Dockerfile 경로에서 Dockerfile이라는 파일을 찾아서 이미지를 빌드한다.
    • 하지만, 필요에따라 다른 이름의 도커파일을 생성해야할 수도 있다
    • 예를 들어 개발 환경 도커를 위해 Dockerfile.dev와 같이 이름짓는 경우에 -f 옵션을 사용해서 도커파일의 이름을 지정해줄 수 있다.
docker build -f Dockerfile.dev -t imagetag .

터미널을 새로 열어, Dockerfile이 있는 디렉토리로 이동한다. 그 후 docker build 명령어로 이미지를 만들고 컨테이너를 실행한다. 명령어를 작성하기 전에 아래 조건을 생각해보자.

  • 컨테이너 포트 80번은 호스트 머신의 9100번 포트에 바인딩 되어야 한다. 어떻게 해야할까?
    • -p 옵션을 9100:80로 설정해야 한다.
  • 컨테이너 실행 옵션은 Attach Mode, Detach Mode중 무엇이 더 알맞은 선택일까?
    • 웹서버이므로 콘솔을 볼 필요 없이 실행이 목적이기 때문에 detach 모드로 실행한다.
$ cd (실습하고 있는 디렉토리)

$ docker build -t imagefromdockerfile .
$ docker run -d --name mycontainer -p 9100:80 imagefromdockerfile

위의 커맨드를 모두 실행했다면 localhost:9100에 접속하면 다음과 같은 화면을 볼 수 있을 것이다.

Dockerfile 문법

명령어 설명
FROM 베이스 이미지 지정, 여러 개 중첩 가능
WORKDIR 작업 디렉터리 설정, 컨테이너 실행 시 바로 해당 경로로 이동
RUN 명령어 실행, shell command
CMD 컨테이너 실행 명령
LABEL 라벨 설정
EXPOSE 컨테이너의 트래픽을 Listening하는 포트 지정, 기본 TCP
ENV 환경 변수 설정
ADD 파일 및 디렉터리 추가
COPY 호스트의 디렉터리나 파일을 이미지 파일 시스템으로 복사
ENTRYPOINT 이미지를 컨테이너로 띄울 때 항상 실행돼야 하는 명령
VOLUME 데이터를 존속시킬 수 있는 볼륨 지정
ARG docker build 명령어에서 -build-arg 옵션을 넘길 수 있는 인자 설정
SHELL 기본 셸 설정

더 자세한Dockerfile 문법은 여기에서 "Dockerfile 문법"을 참고하자.


결론

여기서부터가 도커의 진짜 진짜 시작이 아닐까 생각이 든다. 확실히 어려워지고 더 깊게 들어가면 힘들 것 같다는 생각이 들었다. 나머지 더 딥한 내용들은 강의 자료의 Week4부터 보면 되는데 필요할 때마다 들어가서 보는 방향으로 가야할 것 같다.

스퍼트 프로젝트를 완성해서 Dockerizing까지 완료하는 그날까지..

728x90
Comments