Docker image는 어떠한 application에 대해서 단순히 code뿐만이 아니라 해당 application과 dependency가 있는 모든 것들을 함께 packaging하여 어디서든지 container 형태로 실행시킬 수 있게 만든 data를 의미한다.(Build once, Run anywhere)
Docker에서는 사용자들이 docker image를 쉽게 제작할 수 있도록 template들을 제공해주고 있는데, 이러한 template을 docker file이라고 한다. 그래서 사람들은 docker file을 이용해서 docker image를 손쉽게 만들어낼 수 있다.
지금부터는 docker file을 직접 만들어서 이후에 docker image를 만드는데 도움을 주려고 한다. 그래서 docker file을 직접 만들기 위해서 먼저 다음과 같이 VM에서 folder를 하나 만들어 빈 file을 생성하고자 한다.
$ cd $HOME
$ mkdir docker-practice
$ cd docker-practice
$ touch Dockerfile # Docker file을 만들기 위한 빈 file
$ ls
아무것도 없는 빈 folder에 touch
라는 명령어를 통해서 docker file 하나를 생성한 것을 확인할 수 있다. 이제 docker file을 vi editor나 사용하고 있는 여러 편집기를 이용해서 작성하면 된다.
그전에 docker file에서 사용할 수 있는 기본적인 명령어들이 존재하는데 이를 간단하게 몇가지만 살펴보고 지나가도록 할 것이다. 아무렇게자 작성할 수는 없기 때문에 docker file을 작성할 때 사용되는 명령어들을 알아둬야 한다.
FROM
은 docker file이 처음에 기반이 되는 base image를 어떠한 것으로 사용할지 알려줄 때 사용하는 명령어이다. 보통 docker image를 만들 때 처음부터 끝까지 다 만드는 것이 아니라 처음 일부분은 이미 잘 만들어진 docker image를 그대로 사용하는 경우가 많다. 다음과 같은 형태로 사용하면 된다.
FROM <image>[:<tag>] [AS <name>]
# Examples
FROM ubuntu
FROM ubuntu:18.04
FROM nginx:latest AS ngx
COPY
는 source가 되는 위치에서의 file이나 directory를 destination이 되는 경로에 복사해주는 명령어이다.
COPY <src>... <dest>
# Examples
COPY a.txt /some-directory/b.txt
COPY my-directory /some-directory-2
RUN
은 명시한 명령어들을 docker container에서 실행하는 것을 알려주는 명령어이다. 보통 필요한 package들을 container 내부에 설치하고 사용할 수 있도록 도와주는데 사용된다.
RUN <command>
RUN ["executable-command", "parameter1", "parameter2"]
# Examples
RUN pip install torch
RUN pip install -r requirements.txt
CMD
는 명시한 명령어를 docker container가 시작함과 동시에 실행하도록 하는 명령어이다. CMD와 비슷한 역할을 하는 명령어로 ENTRYPOINT가 있다. 그리고 중요한 내용으로는 하나의 docker image에서는 하나의 CMD
만 실행할 수 있다. 이러한 부분은 RUN
명령어와의 차이점이 된다.
CMD <command>
CMD ["executable-command", "parameter1", "parameter2"]
CMD ["parameter1", "parameter2"] # ENTRYPOINT 와 함께 사용될 때
# Examples
CMD python main.py # Docker container가 실행됨과 동시에 python file 실행
CMD
WORKDIR
은 이 명령어가 사용되고 난 후에 작성되는 모든 명령어들을 container 내에서 어떠한 directory에서 수행할 것인지를 알려주는 명령어이다. 이때 해당 directory가 없을시에는 생성이 된다.
WORKDIR /path/to/workdir
# Examples
WORKDIR /home/test
ENV
는 container 내부에서 계속해서 사용이 될 environtment variable의 값들을 설정하는 명령어이다. 보통은 default 언어를 설정하거나 time zone을 설정하는데 사용된다. 또한 password나 port number같은 중요한 정보를 설정하는데도 사용 될 수 있다.
ENV <key> <value>
ENV <key>=<value>
# Examples
RUN locale-gen ko_KR.UTF-8
ENV LANG ko_KR.UTF-8
ENV LANGUAGE ko_KR.UTF-8
ENV LC_ALL ko_KR.UTF-8
EXPOSE
는 container에서 뚫어 줄 port와 protocol을 지정하는데 사용하는 명령어로, protocol을 지정하지 않게되면 TCP가 default로 설정되게 된다. 예를 들어 다음과 같이 8080을 port로 설정하게 된다면 다음 container는 8080 port가 TCP protocol로 열린채 실행하게 된다.
EXPOSE <port>
EXPOSE <port>/<protocol>
# Examples
EXPOSE 8080
이러한 정보들을 이용해서 간단하게 test용 docker file을 작성해보고자 한다. 이때는 앞서 이야기했듯이 vi editor를 사용해도 좋고 편한 편집기를 찾아서 사용하면 된다.
$ vi Dockerfile
작성한 명령어들을 살펴보면 먼저 base image로 Ubuntu:18.04를 사용하고 apt-get update 명령어를 실행시키고자 한다. Docker container가 시작됨과 동시에 "Hello!"를 출력하도록 한 것이다. 이때 echo
는 뒤에 나오는 argument를 그대로 실행하는 명령어이다.
이렇게 작성이 된 docker file을 저장한 뒤에는 docker build
라는 명령어를 통해서 docker image를 생성할 수 있다. docker build
도 option들이 굉장히 많기 때문에 필요한 내용을 찾아서 사용하면 된다. 본격적으로 docker image를 만들기 위해서 docker file이 있는 위치에서 다음의 명령어를 입력하면 된다.
$ docker build -t test-image:v1.0.0 .
여기서 주의해야되는 부분은 마지막에 사용된 .
으로, 이는 현재 경로에 있는 docker file로부터 build하겠다는 의미를 나타내기에 꼭 사용해줘야 하는 option이다. 그리고 앞에 test-image는 만들어질 docker image의 name이고 콜론 뒤의 숫자는 만들어질 docker image의 tag를 나타낸다.
정상적으로 docker file로부터 docker image가 build 되었는지 확인하기 위해서 다음 명령어를 통해서 확인해보도록 한다.
$ docker images
$ docker images | grep test-image
docker images
만으로도 확인이 가능하지만, docker image가 정말 많은 경우에는 grep
이라는 명령어를 통해서 원하는 docker image만을 출력할 수 있다.
그러면 이제 이렇게 build가 된 docker image로부터 docker container를 실행해보고자 한다.
$ docker run test-image:v1.0.0
그러면 의도한대로 "Hello!"라는 문구가 출력된 것을 확인할 수 있다.
추가적으로 지금 만든 docker image로부터 docker container가 실행되었다는 결과도 확인할 수 있다.
만약 본인이 만든 docker image를 다른 사람들과 공유하고자 할 때 어딘가에 저장을 시켜두고 저장소로부터 docker image를 download 받아서 사용할 수 있으면 협업을 하거나 할 때 굉장히 편리할 수 있다. 이렇게 docker image들을 저장할 수 있는 저장소로는 대표적으로 docker registry와 docker hub가 존재한다.
Docker registry를 사용하는 방법을 알기 위해서는 docker registry의 공식 문서(https://docs.docker.com/registry/)를 참고하면 된다. 복잡한 작업이 아니고 간단하게 docker registry를 VM에 띄워본 다음에 위에서 build한 docker image를 docker registry에 push해보고자 한다. Docker registry의 경우 이미 잘 준비가 된 docker container가 존재하기 때문에 사용하는데 어려움이 전혀 없다. 먼저 다음과 같이 docker registry를 띄워볼 수 있다.
$ docker run -d -p 5000:5000 --name registry registry
$ docker ps
이렇게 하면 우선 "registry"라는 docker image를 download 받아서 background에서 5000번 port로 registry라는 이름의 docker container를 실행할 수 있다. 그리고 docker ps
를 통해서 생성이 된 docker container가 실행되고 있음을 확인할 수 있다.
다음으로는 위에서 build한 test-image라는 docker image를 방금 생성한 registry를 바라보도록 tagging을 할 수 있다. docker push
를 통해서 private registry나 public registry에 docker image를 올릴 때는 tag를 설정해주는 과정이 필요하다.
$ docker tag <option> <image_name>:<tag_name> <registry_address, user_name>/<image_name>:<tag_name>
$ docker tag test-image:v1.0.0 localhost:5000/test-image:v1.0.0
$ docker images | grep test-image
docker images
명령어에 grep
을 이용해서 원래 있었던 docker image와 tagging이 완료된 docker image가 모두 존재하는 것을 확인할 수 있다. 그러면 이제 이 test-image를 생성한 registry에 push할 것이다.
$ docker push localhost:5000/test-image:v1.0.0
정상적으로 push가 되었는지는 다음과 같이 확인할 수 있다.
$ curl -X GET http://localhost:5000/v2/_catalog
$ curl -X GET http://localhost:5000/v2/test-image/tags/list
localhost:5000이라는 registry에 어떠한 image가 저장되어 있는지 확인할 수 있는 명령어와 test-image라는 image name에 어떠한 tag가 저장되어 있는지 확인할 수 있는 명령어를 통해서 push가 잘되었는지 확인할 수 있는 것이다.
방금 생성해서 확인한 docker registry는 private registry로 내 컴퓨터에 접속할 수 있는 사람들이 docker image를 push와 pull을 할 수 있도록 만들어진 공간이다. 이제는 내 컴퓨터의 접속할 수 있는 정보를 모르는 사람들도 대중적으로 docker image를 push, pull할 수 있는 public registry가 바로 docker hub이다. Docker hub는 링크(https://hub.docker.com)를 통해서 접속할 수 있으며, 접속한 후에는 회원 가입을 하고 plan(free, pro, team / personal, pro, team, business)을 설정해서 e-mail 인증까지 마무리하면 정상적으로 docker hub를 사용할 수 있게 된다.
이 과정만 지나면 이제 terminal에 다음 명령어를 통해서 docker login을 하면 된다. 이 과정을 통해서 docker registry로 docker hub를 바라보게 된다.
$ docker login
그리고는 docker hub를 바라보도록 한번더 tag를 만들어주는 작업을 진행한다.
# docker tag <image_name>:<tag_name> <user_name>/<image_name>:<tag>
$ docker tag test-image:v1.0.0 simjy98/test-image:v1.0.0
마지막으로 docker image를 docker hub에 push해주면 docker hub에 local에서 만든 docker image를 올려 다른 사람들과 자유롭게 사용할 수 있다. 그리고 docker hub에서 계정만 알고 있다면 해당 계정이 upload한 docker image를 확인할 수도 있다.