[Docker] 4. 나만의 이미지 생성하기 (ft. Dockerfile)

저번 글에서 Docker Hub에서 만들어놓은 이미지를 다운로드 받아서 구동하는 것을 다뤘는데, 이번에는 Dockerfile을 직접 짜서 나만의 이미지를 만들어보려고 한다.

들어가기 전에,

사실 이 부분에 대해서 이해가 많이 어려웠다. Container에서 필요한 프로그램들을 다운로드 받고 commit 명령어를 사용해서 이미지를 만들어도 될텐데, 왜 굳이 Dockerfile을 bash 명령어를 써가며 이미지를 빌드해야 되는지 몰랐다.

그렇게 찾아본 결과 commit 명령어를 사용해서 이미지를 생성하는 방법은 실무에서 거의 쓰이지 않는다고 한다. 패키지 업데이트도 힘들고, 버전 관리도 까다로워서 Dockerfile을 파일화해서 관리하는 것이 버전 관리나 패키지 업데이트 등의 면에서도 우월하다는 것이다.


이제 Dockerfile을 만들어보자.

Dockerfile은 Docker 이미지 설정 파일이다. 이 파일에 설정된 내용대로 이미지를 생성한다. 먼저 example 디렉토리를 생성한 뒤 해당 디렉토리로 이동한다. 모든 빌드와 관련된 파일들이 한 폴더(example)에서 이루어진다.

mkdir example
cd example
cs

이 글에서 다루는 이미지 빌드는 모든 과정을 Dockerfile과 쉘 스크립트 파일로 통합하는 방법이다. (그러면 build-run.sh 파일을 만들고 인자를 전달해서 실행하면 이미지를 만들고 컨테이너로 run까지 one-click으로 할 수 있게 된다)

Dockerfile 관련 명령어

Dockerfile을 만들기 전에 필요한 명령어들을 몇 개 알아보자.

FROM

어떤 이미지를 기반으로 할지 설정한다. Docker 이미지는 기존에 만들어진 이미지를 기반으로 생성한다. 만약 완전히 새로운 이미지를 생성하고 싶으면("맨 땅에서 시작한다") FROM scratch를 쓰면 된다.

MAINTAINER

메인테이너(제작자) 정보이다. Author(저자)라고 생각하면 된다.

RUN

쉘 스크립트/명령을 실행한다.
+ 이미지 생성 중에는 사용자 입력을 받을 수 없다. 그래서 apt-get install 명령어를 사용할 경우 -y 옵션을 붙여야 한다.

VOLUME

호스트와 공유할 디렉터리 목록이다. docker run 명령어에서 -v 옵션으로 설정할 수도 있다.

ADD

빌드시에 주어진 컨텍스트에서 첫번째 인자로 주어진 파일, 폴더를 두번째 인자로 주어진 컨테이너 경로에 추가한다.

CMD

컨테이너가 시작되었을 때 실행할 실행 파일/쉘 스크립트이다.

EXPOSE

호스트와 연결할 포트 번호이다. 외부와 통신을 가능하게 노출시켜 준다. 기본적으로 컨테이너 실행시 docker run -p 옵션을 주게 되면 암묵적으로 EXPOSE가 된다.

이 명령어들을 바탕으로 ubuntu 18.04 기반의 xrdp, vim 등의 필수 패키지들이 설치된 나만의 우분투 이미지 Dockerfile을 만들어 보았다.

Dockerfile
FROM ubuntu:18.04
#set root password
RUN echo "root:ubuntu" | chpasswd
# install packages
RUN apt-get update \
    && apt-get install --yes --force-yes --no-install-recommends \
        sudo \
        software-properties-common \
        xorg \
        xserver-xorg \
        xfce4 \
        gnome-themes-standard \
        gtk2-engines-pixbuf \
        file-roller \
        evince \
        gpicview \
        leafpad \
        xfce4-whiskermenu-plugin \
        ttf-ubuntu-font-family \
        dbus-x11 \
        vnc4server \
        vim \
        xfce4-terminal \
        xrdp \
        xorgxrdp
# add the user and designate sudo authority
RUN adduser ubuntu
RUN echo "ubuntu:ubuntu" | chpasswd
RUN echo "ubuntu ALL=(ALL:ALL) ALL" >> /etc/sudoers
#set the port number of xrdp
RUN sed -'s/3389/port_number/' /etc/xrdp/xrdp.ini
#install xubuntu-desktop
RUN apt-get install --yes --force-yes --no-install-recommends \
        xubuntu-desktop \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# insert entrypoint.sh and set ENTRYPOINT
ADD entrypoint.sh /entrypoint.sh
ENTRYPOINT /entrypoint.sh
cs

여기서

RUN sed -'s/3389/port_number/' /etc/xrdp/xrdp.ini
cs

sed 명령어는 파일에 있는 특정 단어를 찾아서 다른 단어로 바꾸는 역할을 한다.
자세한 내용은 http://millky.com/@origoni/post/664 을 참조하기 바란다.

ENTRYPOINT
/entrypoint.sh
ENTRYPOINT 명령어는 컨테이너가 처음 실행될 때(run/start 시) 한번 수행되는 스크립트를 지정한다. 따라서 이미지를 빌드하고 컨테이너로 run하면 entrypoint.sh 쉘 스크립트가 실행된다.

entrypoint.sh
#!/bin/bash
# create a dbus system daemon
service dbus start
# create the sock dir properly
/bin/sh /usr/share/xrdp/socksetup
# run xrdp and xrdp-sesman in the foreground so the logs show in docker
xrdp-sesman -ns &
xrdp -ns &
#run shell for interface
/bin/bash
cs

dbus, xrdp 서비스를 위한 entrypoint 설정이다.

이제 이미지 빌드에 필요한 Dockerfile, entrypoint.sh를 만들었으니 docker run에 필요한 최종 파일인 build-run.sh 파일을 만들어보자.

build-run.sh
#!/bin/bash
#edit the port number in Dockerfile
sed -'s/port_number/'$1'/' ./Dockerfile
#start building image from Dockerfile
docker build -t $2 .
#run container from built image
docker container run --it --name $3 -p $1:$1 $2
docker container start $3
#return Dockerfile into first state
sed -'s/'$1'/port_number/' ./Dockerfile
cs

$1, $2, $3은 build-run.sh의 인자 번호이다.

./build-run.sh [포트번호] [이미지 이름] [컨테이너 이름]
cs

위 명령어를 실행하게 되면 해당 포트 번호, 이미지 이름, 컨테이너 이름으로 이미지 빌드, 실행(run)까지 완료하게 된다.

이미지 빌드에는 시간이 다소 걸린다. 잘 참고 기다리면 나만의 이미지가 생성된다. 이 이미지를 도커 허브에 올려보고 다른 os 기반에서 다운로드 받아서 컨테이너에 올려보자.

댓글 없음:

Powered by Blogger.