ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Docker] 나를 위한 도커 개념 정리
    Docker 2022. 11. 23. 10:25

    수시로 도커를 접하면서 접할 때마다 "도커가 정확히 뭐지?"라는 의문을 해소하기 위한 나만의 정리 글.


    도커란 무엇인가?

    도커는 컨테이너 기반의 오픈소스 가상화 플랫폼.

     

    어떠한 프로그램도 컨테이너로 만들 수 있고, 어떠한 환경에서도 실행가능하다.(ex: AWS, GCP...)

     

    그렇다면 도커는 가상머신인가?

    • 가상머신 처럼 독립적으로 실행되지만 가상머신보다 빠르고 가상머신보다 쉽고 가상머신보다 효율적이다.

     

    도커의 특징

    확장성/이식성

    • 도커가 설치되어 있다면 어디서든 컨테이너를 실행할 수 있음
    • 특정 회사나 서비스에 종속적이지 않음
    • 쉽게 개발서버를 만들 수 있고 테스트서버 생성도 간편함

    표준성

    • 도커를 사용하지 않는 경우 각 언어로 만든 서비스들의 배포 방식은 서로 상이함
    • 컨테이너라는 표준으로 서버를 배포하므로 모든 서비스들의 배포과정이 동일해짐

    이미지

    • 이미지에서 컨테이너를 생성하기 때문에 반드시 이미지를 만드는 과정이 필요
    • Dockerfile을 이용하여 이미지를 만들고 처음부터 재현 가능
    • 빌드 서버에서 이미지를 만들면 해당 이미지를 이미지 저장소에 저장하고 운영서버에서 이미지를 불러옴

    설정관리

    • 설정은 보통 환경변수로 제어함
    • MYSQL_PASS=pwd와 같이 컨테이너를 띄울 때 환경변수를 같이 지정
    • 하나의 이미지가 환경변수에 따라 동적으로 설정파일을 생성하도록 만들어져야함

    자원관리

    • 컨테이너는 삭제 후 새로 만들면 모든 데이터가 초기화됨
    • 업로드 파일을 외부 스토리지와 링크하여 사용하거나 S3같은 별도의 저장소가 필요
    • 세션이나 캐시를 memcached나 redis와 같은 외부로 분리

     

    도커가 가져온 변화

    • 클라우드 이미지보다 관리하기 쉬움
    • 다른 프로세스와 격리되어 가상머신처럼 사용하지만 성능저하가 거의 없음
    • 복잡한 기술을 몰라도 사용할 수 있음
    • 이미지 빌드 기록이 남음
    • 코드와 설정으로 관리 > 재현 및 수정 가능
    • 오픈소스 > 특정 회사 기술에 종속적이지 않음

    docker-compose 란? (https://wooono.tistory.com/123)

    다수의 컨테이너가 유기적으로 묶여 하나의 어플리케이션으로 동작이 필요한 경우 유용하게 사용할 수 있는 기능, 연결된 다수의 container를 하나로 통합하여 관리 하는 도구. ex) 웹 서비스를 한다고 했을 때 웹 서버와 데이터베이스등이 포함된 컨테이너를 생성해야 한다.

     

    도커로만 해당 서비스를 하려고 하면 매번 docker run 명령어를 통해 각 컨테이너를 생성해야 한다. docker-compose는 이런 문제를 해결하고자 여러 컨테이너를 하나의 서비스로 묶어 다룰 수 있게 해준다. (docker-compose.yml 파일을 통해 설정함)

     

    유의 사항

    • docker-compose는 host level에서만 동작한다.
    • docker swarm에 배포 하기 위해서는 docker stack deploy를 사용해야 한다.

    docker-compose.yml

    • container실행 옵션을 미리 정의한 문서다.
    • docker-compose를 docker-compose.yml에 정의에 맞게 container를 실행한다.

    docker-compose.yml 형식 (https://docs.docker.com/compose/compose-file/#service-configuration-reference)

    # 버전 정의, 버전에 따라서 지원하는 형식이 다르다. 일반적으로 3.0을 사용
    version: '3.0'
    
    # docker-compose로 생성 할 container의 옵션을 정의한다.
    # service안의 container들은 하나의 project로서 docker-compose로 관리된다.
    services:
    
        # 생성할 container 이름을 지정한다. ex) gateway, base-user..
        container-이름:
        
            # container 생성시 사용할 이미지 지정, 로컬에 이미지가 있으면 해당 이미지를 사용,
            # 그렇지 않다면 도커 허브에서 이미지 다운로드 후 사용.
            image: node-server:v1
            
            # 컨테이너의 특정 폴더를, 호스트 시스템(OS)에 연결해, 
            # 컨테이너가 삭제되더라도, 데이터를 유지할 수 있도록하는 것을 볼륨이라 함.
            # https://medium.com/dtevangelist/docker-%EA%B8%B0%EB%B3%B8-5-8-volume%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-data-%EA%B4%80%EB%A6%AC-9a9ac1db978c
            volumes: ... 경로 설정
            
            # ex) mysql volumes 설정 중..
            # 문법 = 호스트 디렉토리(./init/admin):컨테이너 디렉토리(/docker-entrypoint-initdb.d)
            # 호스트 디렉토리와 컨테이너 디렉토리를 마운트
            volumes: 
              - ./init/admin:/docker-entrypoint-initdb.d
              
            # restart 옵션 
            # https://docs.docker.com/compose/compose-file/compose-file-v3/#restart
            restart: no/always/on-failure/unless-stopped
            
            # Dockerfile entrypoint 보다 우선 실행 됨.
            entrypoint: ... shell 명령어
            
            # docker-compose build 옵션에서 사용된다.
            # build 옵션을 사용하면 Dockerfile을 이용하여 이미지를 자체적으로 빌드하는 것.
            build:
                context: ... # dockerfile의 위치를 지정.
                dockerfile: ... # 파일명이 Dockerfile이 아닌 경우 기입.
                
            # ports 설정 (아래 설명)
            ports:
                - "80:80" # 호스트포트:컨테이너포트
    
            # expose 설정 (아래 설명)
            expose:
                - "80"
            
            # 의존관계를 설정 아래와 같이 설정되어 있으면 db, redis service가 실행되고 이 서비스가 실행됨.
            # https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on
            depends_on:
              - db
              - redis
    
            # 환경 변수 리스트를 정의.
            environment:
                UPDATE_URL: "https://www.doitnow-man.com"
                
            #실행 환경 설정
            stdin_open: true       # docker run -i
            tty: true              # docker run -t
            entrypoint: /bin/bash  # exec /bin/bash

     

    ports (https://growd.tistory.com/77)

    db:
      image: mysql:latest
      ports:
        - "3307:3306"
    node:
      image: node:latest

    위와 같이 설정되어 있으면 mysql 컨테이너는 컨테이너 내부의 3306포트가 호스트의 3307 포트로 매핑이 되게 된다. 위의 node 컨테이너는 3307 포트로 mysql 컨테이너로 액세스가 가능하고 다른 호스트 또한 위 호스트의 3307 포트로 mysql 컨테이너에 액세스가 가능하게 된다.

     

    expose (https://growd.tistory.com/77)

    db:
      image: mysql:latest
      expose:
        - "3306"
    node:
      image: node:latest

    위의 mysql 컨테이너는 호스트 내부에서 3306포트를 노출하게 된다. node 컨테이너는 3306 포트로 mysql 컨테이너에 액세스가 가능하지만 호스트 외부의 다른 호스트들을 mysql 컨테이너로 액세스가 불가하다.


    Dockerfile 이란? (https://wooono.tistory.com/123)

    Dockerfile은 DockerImage를 생성하기 위한 스크립트(설정파일)이다.

     

    여러가지 명령어를 토대로 Dockerfile을 작성한 후 빌드하면 Docker는 Dockerfile에 나열된 명령문을 차례대로 수행하며 DockerImage를 생성해준다.

     

    Dockerfile을 읽을 줄 안다는 것은 해당 이미지가 어떻게 구성되어 있는지 알 수 있다는 의미이다.

    문법 (https://doitnow-man.tistory.com/entry/8-Dockerfile-%EA%B3%BC-Docker-composeyml)

    #FROM
    # 베이스 이미지를 지정합니다. 반드시 지정해야 하며 어떤 이미지도 베이스 이미지가 될 수 있습니다.
    # tag는 될 수 있으면 latest(기본값)보다 구체적인 버전(16.04등)을 지정하는 것이 좋습니다.
    # 이미 만들어진 다양한 베이스 이미지는 Docker hub에서 확인할 수 있습니다.
    # FROM <image>:<tag>
    FROM ubuntu:16.04
     
     
    #MAINTAINER
    # Dockerfile을 관리하는 사람의 이름 또는 이메일 정보를 적습니다. 빌드에 딱히 영향을 주지는 않습니다.
    # MAINTAINER <name>
    MAINTAINER jinwkon.kim@ahnlab.com
     
     
    #COPY
    # 파일이나 디렉토리를 이미지로 복사합니다. 일반적으로 소스를 복사하는 데 사용합니다. target디렉토리가 없다면 자동으로 생성합니다.
    # COPY <src>... <dest>
    COPY . /usr/src/app
     
     
    #ADD
    # COPY명령어와 매우 유사하나 몇가지 추가 기능이 있습니다. src에 파일 대신 URL을 입력할 수 있고 src에 압축 파일을 입력하는 경우 자동으로 압축을 해제하면서 복사됩니다.
    # ADD <src>... <dest>
    ADD . /usr/src/app
     
     
    #RUN
    # 가장 많이 사용하는 구문입니다. 명령어를 그대로 실행합니다. 내부적으로 /bin/sh -c 뒤에 명령어를 실행하는 방식입니다.
    # RUN <command>
    # RUN ["executable", "param1", "param2"]
    RUN bundle install
     
     
    #CMD
    # 도커 컨테이너가 실행되었을 때 실행되는 명령어를 정의합니다.
    # 빌드할 때는 실행되지 않으며 여러 개의 CMD가 존재할 경우 가장 마지막 CMD만 실행됩니다.
    # 한꺼번에 여러 개의 프로그램을 실행하고 싶은 경우에는 run.sh파일을 작성하여 데몬으로 실행하거나 supervisord나 forego와 같은 여러 개의 프로그램을 실행하는 프로그램을 사용합니다.
    #CMD ["executable","param1","param2"]
    #CMD command param1 param2
    CMD bundle exec ruby app.rb
     
     
    #WORKDIR
    # RUN, CMD, ADD, COPY등이 이루어질 기본 디렉토리를 설정합니다.
    # 각 명령어의 현재 디렉토리는 한 줄 한 줄마다 초기화되기 때문에 RUN cd /path를 하더라도 다음 명령어에선 다시 위치가 초기화 됩니다.
    # 같은 디렉토리에서 계속 작업하기 위해서 WORKDIR을 사용합니다.
    WORKDIR /path/to/workdir
     
    #EXPOSE
    # 도커 컨테이너가 실행되었을 때 요청을 기다리고 있는(Listen) 포트를 지정합니다. 여러개의 포트를 지정할 수 있습니다.
    # EXPOSE <port> [<port>...]
    EXPOSE 4567
     
     
    #VOLUME
    # 컨테이너 외부에 파일시스템을 마운트 할 때 사용합니다. 반드시 지정하지 않아도 마운트 할 수 있지만, 기본적으로 지정하는 것이 좋습니다.
    VOLUME ["/data"]
     
     
    #ENV
    # 컨테이너에서 사용할 환경변수를 지정합니다. 컨테이너를 실행할 때 -e옵션을 사용하면 기존 값을 오버라이딩 하게 됩니다.
    # ENV <key> <value>
    # ENV <key>=<value> ...
    ENV DB_URL mysql

    나만의 결론

    • 이미지(정적인 파일, 각종 환경설정)을 바탕으로 컨테이너를 만들어서 서비스를 실행한다.
    • 도커를 쓰는 여러 이유가 있지만 크게 두 가지가 있다.
      • 환경에 구애받지 않는 앱 제작.
      • CI/CD 구성 용이성.

     

    출처 : https://www.inflearn.com/course/%EB%8F%84%EC%BB%A4-%EC%9E%85%EB%AC%B8/

    댓글