들어가며


프로그래밍을 하면서 간간히 도커를 사용한 경험이 있습니다. 맥에서 우분투 환경을 돌리기 위해서 사용한 때도 있고, 42서울에서 프로젝트를 위해 사용한 때도 있습니다.

그 경험을 바탕으로 도커가 무엇이고, 관련한 개념들을 이 글에 정리해놓으려고 합니다.


도커 실행해보기


Docker container

도커가 어떻게 사용되는지를 먼저 보고 도커가 무엇인지 살펴보면 도커를 이해하기 수월할 것 같습니다. 그러므로 바로 도커를 어떻게 사용하는지 살펴보시죠.

도커로 사람들이 우분투를 돌리고, 웹서버를 돌리고 많이하는데 도대체 뭘 하는 걸까요?

그 사람들은 docker container를 실행하고 있는 것인데 이 docker container의 정의는 다음과 같습니다.

A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.

위 문장에서 말하는 application이란 소프트웨어 프로그램, 서비스를 의미합니다.

즉 container란, 어떤 프로그램을 돌리는데 필요한 코드, 환경 등을 전부 포함한 소프트웨어입니다. 그래서 다른 사람에게 이식해도 그 사람이 도커를 이용해서 continaer를 돌리기만 하면 원래 어떤 환경을 사용하든 상관없이 균일한 결과를 얻을 수 있게 해주죠.

이런 container를 만드는 방법도 간단합니다. Docker image라는 것이 있기때문이죠.


Docker Image

Docker image란 무엇일까요? 이 역시 공식 홈페이지에 의하면 아래와 같습니다.

An image is a read-only template with instructions for creating a Docker container.

A container is a runnable instance of an image.

Docker image안에는 우리가 원하는 애플리케이션을 실행시키기 위한 모든 것들이 들어가있습니다. 이것들을 찍어내기만하면 container가 만들어지는 것이죠. 이 image의 예시로는 ubuntu, nginx 등 많은 애플리케이션들이 있습니다.


Example

개념들을 듣고나도 어떻게 돌아가는지 알아야 이해가 더 잘 가겠죠? 한번 우분투가 돌아가는 container를 만들어봅시다.

우선 Docker Desktop을 깔고 Docker를 실행시켜둡니다. 그러면 아래 그림과 같이 나올 것입니다.

그 후 터미널에서 아래와 같은 명령어를 칩니다. 아래의 명령어는 ubuntu 이미지를 가져와서 myubuntu라는 이름의 container를 만드는 작업입니다. -i 옵션은 container의 stdin을 키는 것이고 -t 옵션은 container에 가상 터미널을 할당해줍니다.


docker run --it --name myubuntu ubuntu

그러면 이렇게 container가 만들어진 모습을 확인할 수 있습니다. 물론 도커 데스크탑을 키지않고 docker container ls -a라고 터미널에 입력해도 바로 확인할 수 있습니다.

그러면 실행을 시켜볼까요? 실행을 시키려면 도커 데스크탑에서 실행버튼을 눌러주거나 container ID를 가져와서 start로 실행을 시키고 attach로 터미널을 붙여주면 됩니다.


docker start <container ID>

docker attach <container ID>

그러면 아래와 같이 터미널을 통해 우분투 환경을 이용할 수 있게 됩니다!


도커 직접 구성해보기


Docker File

지금까지는 가장 기초적인 Docker 사용법을 배워보았습니다. 원하는 이미지를 가져와서 docker container를 만들고, 실행시켜서 사용하는 것이죠.

그런데 만약 내가 원하는대로 설정된 이미지를 만들고싶다면 어떻게 해야할까요? 예를 들어 ubuntu도 설치되어있고, nginx 웹서버도 설치되어있고, 설정도 제가 원하는대로 해놓은 이미지 말입니다.

이를 위해서 Docker file 이라는 것이 존재합니다.

Docker file 안에는 아래와 같은 여러 instructions 들을 적어놓을 수 있습니다. 원하는 instruction을 적은 후 Dockerfile을 build하면 원하는 이미지가 만들어지는 것이죠.


InstructionDescription
ADDAdd local or remote files and directories.
ARGUse build-time variables.
CMDSpecify default commands.
COPYCopy files and directories.
ENTRYPOINTSpecify default executable.
ENVSet environment variables.
EXPOSEDescribe which ports your application is listening on.
FROMCreate a new build stage from a base image.

그리고 실제로 사용하는 예는 다음과 같습니다.

아래의 dockerfile은 debian의 bullseye 버전을 기본 이미지로 삼은 후 RUN에 있는 여러 명령어들을 실행합니다. 그 후 nginx configuration 파일들을 복사하고 CMD를 통해 실행할 명령어를 적어둡니다.

이 dockerfile을 통해서 image를 빌드하게된다면 debian 이미지 위에 추가적인 작업들을 한 고유의 이미지가 만들어지는 것입니다.

FROM debian:bullseye

RUN apt-get update && \
    apt-get upgrade && \
    apt-get install -y nginx && \
	...
    
COPY nginx.conf /etc/nginx/nginx.conf

# Start Nginx in the foreground
CMD ["nginx", "-g", "daemon off;"]

Docker Compose

지금까지는 하나의 컨테이너만을 다뤘지만 실제로는 여러 컨테이너들이 서로 연결되고 동작하기도 합니다. 예를 들어 한 컨테이너에 웹서버, 한 컨테이너에 데이터베이스, 한 컨테이너에 php를 실행시켜두고 셋을 연결하여 웹서비스를 구현할 수도 있겠죠.

이렇게 멀티 컨테이너 환경을 손쉽게 다루기 위하여 있는 것이 Docker compose입니다.

단 하나의 YAML파일로 어떤 컨테이너를 어떤 이미지나 docker file로 만들 것인지, 어떤 컨테이너들을 한 네트워크로 묶어서 관리할 것인지 등을 설정할 수 있습니다.

아래와 같이 말입니다. 아래의 docker compose 파일은 nginx, wordpress, mariaDB 세개의 컨테이너를 만들고 하나의 네트워크로 구성하는 내용을 담았습니다.

nginx 컨테이너를 만드는 예시를 보면 nginx이미지를 가져오는데 그 이미지는 srcs/nginx에 있는 dockerfile을 사용해서 만들라고 되어있고 제 컴퓨터의 443포트와 컨테이너의 443포트를 연결하라고 되어있습니다.

자세한 내용은 Inception에서 확인할 수 있습니다.

version: '3.8'

volumes:
  wp:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /home/jukim2/data/wordpress
  db:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /home/jukim2/data/mariaDB
    
networks:
  inception:

services:
  nginx:
    image: nginx
    build: srcs/nginx
    ports: 
      - "443:443"
    volumes:
      - "wp:/var/www/html"
    networks:
      - inception
    depends_on:
      - wordpress

  wordpress:
    image: wordpress
    build: srcs/wordpress
    expose:
      - 9000
    volumes:
      - "wp:/var/www/html"
    networks:
      - inception
    env_file:
      - .env
    depends_on:
      - mariadb

  mariadb:
    image: mariadb
    build: srcs/mariaDB
    volumes:
      - "db:/var/lib/mysql"
    expose:
      - 3306
    env_file:
      - .env
    networks:
      - inception

Docker

이제 도커를 어떻게 사용하는지는 좀 알 것 같습니다.

그렇다면 도커란 결국 무엇일까요? 그 정의는 아래에 정확하게 나와있습니다.

Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly.

만약 이 정의를 처음부터 보았다면 잘 이해가 가지않았겠지만 도커를 이루는 docker container, docker image 등을 알고 나니 왜 도커란 application의 개발, 배송, 실행을 위한 플랫폼이라는 것인지 이해가 가시죠?


마무리


이렇게 쭉 도커를 어떻게 사용해야하는지를 통해 도커란 무엇인지 쭉 공부를 해보았습니다.

지금 당장은 언제 쓰일지 몰라도 이를 바탕으로 도커 활용법을 잘 익혀두시면 언젠가 유용하게 쓰이실 것입니다.

감사합니다.