초보자를 위한 Docker: 배포 악몽에 작별 인사!

초보자를 위한 Docker: 배포 악몽에 작별 인사!

초급 개발자는 종종 비효율적인 코드 업데이트, 릴리스 및 배포와 같은 문제와 환경 일관성 유지의 어려움에 직면합니다. 개발 환경에서 원활하게 실행되던 코드가 다른 머신에서는 오류를 발생시킬 수 있습니다. 클라우드 컴퓨팅 시대에 전통적인 방법을 사용하여 코드를 배포하는 것은 시대에 뒤떨어진 느낌입니다. 이 블로그 게시물에서는 Docker를 소개합니다.

Docker는 Go 언어를 기반으로 하며 Apache 2.0 라이선스 하에 오픈소스로 제공되는 애플리케이션 컨테이너 엔진입니다. 이 컨테이너화 기술을 통해 개발자는 애플리케이션과 종속성을 가볍고 이식 가능한 컨테이너에 패키징할 수 있습니다. 이러한 컨테이너는 환경 차이를 걱정할 필요 없이 모든 인기 있는 Linux 머신에 배포할 수 있습니다.

Docker vs. ** 가상 머신(VM)**

앞서 언급했듯이 Docker는 가상화를 활용합니다. 가상화에 대해 논할 때 가상 머신(VM)은 자연스럽게 언급됩니다. 둘 다 가상화에 의존하기 때문에 그 차이점이 무엇인지 궁금해지기 마련입니다. 이에 대해 자세히 알아보겠습니다.

먼저 일반적인 VM 아키텍처 다이어그램을 살펴보겠습니다. 인프라(기본 하드웨어를 나타냄) 위에 하이퍼바이저가 있습니다. 물리적 서버와 운영 체제 간의 중개자 역할을 하여 여러 운영 체제와 애플리케이션이 기본 하드웨어를 공유할 수 있도록 합니다. 가상 머신은 호스트 운영 체제 위에 여러 개의 고유한 운영 체제를 실행하고 하이퍼바이저를 사용하여 기본 하드웨어에 액세스합니다.

세 개의 격리된 애플리케이션을 실행해야 하는 경우 세 개의 가상 머신을 생성합니다. 즉, 하이퍼바이저 위에 세 개의 운영 체제가 실행되어 상당한 리소스 오버헤드가 발생합니다.

일반적인 VM 아키텍처 다이어그램

(참고: 다이어그램은 이상적으로 하이퍼바이저 위에 호스트 운영 체제를 표시해야 합니다.)

반면 Docker는 매우 가볍습니다. 데몬(Docker Daemon)이 하이퍼바이저를 대체하여 운영 체제에서 직접 실행됩니다. 애플리케이션의 소스 코드와 종속성은 Docker 이미지로 패키징됩니다. 그런 다음 Docker 엔진은 이 이미지를 사용하여 컨테이너를 생성합니다. 다른 애플리케이션은 격리된 컨테이너에서 실행됩니다.

또한 Docker 데몬은 운영 체제와 직접 통신하여 Docker 컨테이너에 리소스를 할당합니다. 전체 운영 체제의 오버헤드가 없기 때문에 컨테이너 시작 시간이 가상 머신의 분 단위에서 Docker 컨테이너의 밀리초 단위로 단축되어 효율성이 크게 향상되고 상당한 디스크 공간 및 기타 시스템 리소스가 절약됩니다.

Docker는 매력적인 장점을 제공하지만 가상 머신을 완전히 대체하지는 않습니다. 각 기술에는 고유한 강점이 있습니다. 가상 머신은 전체 런타임 환경을 격리하는 데 탁월하며, 클라우드 제공업체가 VM을 통해 사용자를 분리하는 데 일반적으로 사용됩니다. Docker는 일반적으로 다른 애플리케이션을 격리합니다.

Docker 사용 방법

Docker 설치(CentOS 7 예시)

  1. 필수 시스템 도구 설치:
yum install -y yum-utils device-mapper-persistent-data lvm2 
  1. 시스템 커널 및 yum 캐시 업데이트:
yum update
yum makecache fast
  1. Docker 설치 및 시작:
yum -y install docker-ce
systemctl start docker 
  1. Docker가 성공적으로 설치되었는지 테스트:
docker run hello-world 

화면에 "Hello from Docker"가 표시되면 축하합니다! 설치가 완료된 것입니다.

개념

Docker에 대해 더 깊이 알아보기 전에 더 원활한 학습을 위해 몇 가지 주요 개념을 살펴보겠습니다.

  1. Docker 이미지: Docker 이미지는 Docker 컨테이너를 생성하는 데 사용되는 템플릿입니다.
  2. Docker 컨테이너: Docker는 이미지를 통해 컨테이너를 생성하여 일련의 독립적인 애플리케이션을 실행합니다.
  3. Docker 레지스트리: 이미지를 저장하는 코드 저장소입니다.

일반적으로 Docker 레지스트리에서 적절한 이미지를 다운로드하고 이를 사용하여 애플리케이션을 실행하기 위한 컨테이너를 생성합니다.

예제

두 가지 일반적인 예제를 통해 이러한 개념을 연결하여 Docker 사용 방법을 설명하겠습니다.

Docker로 Python 설치

앞서 언급했듯이 Docker 컨테이너를 사용하는 첫 번째 단계는 저장소에서 해당 이미지를 다운로드하는 것입니다. 이 튜토리얼의 첫 번째 명령어로 이어집니다.

  • 목적: 이미지 저장소에서 특정 이미지를 검색합니다.
  • 구문: docker search [OPTIONS] TERM
  • 예제: docker search python
  • 설명: 저장소에서 Python 관련 이미지를 검색합니다.
[root@novita ~]# docker search pythonINDEX       NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/python                           Python is an interpreted, interactive, obj...   4356      [OK]
docker.io   docker.io/django                           Django is a free web application framework...   856       [OK]
docker.io   docker.io/pypy                             PyPy is a fast, compliant alternative impl...   196       [OK]
docker.io   docker.io/kaggle/python                    Docker image for Python scripts run on Kaggle   125                  [OK]
docker.io   docker.io/arm32v7/python                   Python is an interpreted, interactive, obj...   38
docker.io   docker.io/centos/python-35-centos7         Platform for building and running Python 3...   36

태그(버전) 3.7이 있는 공식 이미지를 선택하겠습니다.

docker pull

  • 목적: 이미지 저장소에서 지정된 이미지를 가져오거나 업데이트합니다.
  • 구문: docker pull [OPTIONS] NAME:TAG
  • 예제: docker pull python:3.7
  • 설명: 저장소에서 태그 3.7이 있는 Python 이미지를 다운로드합니다.
[root@novita ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============>                                     ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================>      ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==>                                                ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7

Docker가 지정된 이미지를 다운로드했습니다. 기존 Docker 이미지를 보려면:

docker images

  • 목적: 로컬 이미지를 나열합니다.
  • 구문: docker images [OPTIONS] [REPOSITORY[:TAG]]
  • 예제: docker images
  • 설명: 모든 로컬 Docker 이미지를 봅니다.
[root@novita ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker.io/python        3.7                 42d620af35be        6 days ago          918 MB
docker.io/rabbitmq      3-management        7aae48fa6ef6        7 days ago          179 MB
docker.io/golang        latest              f50db16df5da        9 days ago          774 MB

python3.7 이미지가 있습니다. 이를 사용하여 컨테이너를 생성해 보겠습니다.

docker run

컨테이너를 생성하기 전에 ID에 대해 간략히 설명하겠습니다. Docker에서 ID는 이미지 또는 컨테이너를 고유하게 식별합니다. "명령어 + ID"를 사용하여 상호 작용합니다. 예를 들어, 이전 코드에서 python3.7의 이미지 ID는 42d620af35be입니다.

  • 목적: 새 컨테이너를 생성합니다.
  • 구문: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

Python 환경을 테스트하기 위해 로컬에서 hello.py 파일을 생성해 보겠습니다.

#!/usr/bin/python 
import sys 

print("Hello, Docker!") 
print(sys.version)  # Output the Python version number 

이 코드가 /root/code/python에 저장되어 있다고 가정합니다.

[root@novita python]# docker run  -v $PWD:/usr/src/code  -w /usr/src/code python:3.7 python hello.py 
Hello, Docker! 
3.7.4 (default, Jul 13 2019, 14:04:11) [GCC 8.3.0] 

이 명령어를 분석해 보겠습니다.

  • docker run: 컨테이너를 생성합니다.
  • -v $PWD:/usr/src/code: 로컬 디렉토리를 Docker 컨테이너에 마운트합니다. 여기서는 명령어가 실행된 디렉토리를 컨테이너 내부의 /usr/src/code에 마운트합니다. 콜론은 로컬 경로와 컨테이너 경로를 구분합니다. $PWD 대신 절대 경로를 사용할 수 있습니다.
  • -w /usr/src/code: 컨테이너의 작업 디렉토리를 설정합니다. Python 코드 디렉토리가 /usr/src/code에 마운트되었으므로 이를 작업 디렉토리로 설정합니다.
  • python:3.7: 사용할 이미지를 지정합니다. 이미지 ID를 대신 사용할 수 있습니다.
  • python hello.py: 컨테이너 내에서 이 명령어를 실행합니다.

생각해보기: /root/data/에 hello.go 파일이 있고 이미지 ID가 f50db16df5da인 Golang 컨테이너를 사용하여 실행하려면 명령어는 무엇일까요? (힌트: Go 코드를 실행하는 명령어는 go run FILENAME입니다.)

Docker로 MariaDB 설치

이제 MariaDB 이미지를 검색하고 다운로드할 수 있다고 가정하고, 시작하는 방법에 초점을 맞추겠습니다. 데이터베이스와 같은 서비스는 호스트에서 해당 포트를 열어야 합니다. Docker에서는 이를 어떻게 달성할까요? 디렉토리 마운트와 유사하게 포트 매핑을 사용합니다.

[root@novita python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456  --restart unless-stopped 3a2ef06682ac 
  • -d: 컨테이너를 백그라운드에서 실행합니다.
  • -p 3306:3306: 컨테이너의 3306 포트를 호스트의 3306 포트에 매핑합니다.
  • -e MYSQL_ROOT_PASSWORD=123456: MariaDB의 루트 비밀번호를 123456으로 설정합니다.
  • --restart unless-stopped: 예기치 않게 중지될 경우 컨테이너를 자동으로 다시 시작합니다.
  • 3a2ef06682ac: 컨테이너를 생성할 이미지 ID입니다.

이제 데이터베이스 서비스가 실행 중인지 확인해 보겠습니다.

docker ps

  • 목적: 컨테이너를 나열합니다.
  • 구문: docker ps [OPTIONS]
[root@novita ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
107b52416c13        3a2ef06682ac        "docker-entrypoint..."   5 minutes ago       Up 5 minutes        0.0.0.0:3306->3306/tcp                                                                       quizzical_mcnulty 

다음으로, 컨테이너의 내부 환경에 접속합니다.

docker exec

  • 목적: 실행 중인 컨테이너에서 명령어를 실행합니다.
  • 구문: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
  • 예제: docker exec -it 107b52416c13 bash
  • 설명: ID가 107b52416c13인 컨테이너에 접속하여 bash 명령어를 실행합니다.

컨테이너 내부에서 일반 Linux 환경과 마찬가지로 상호 작용할 수 있습니다. 이전에 설정한 자격 증명을 사용하여 MariaDB에 접속할 수 있습니다.

[root@novita ~]# docker exec -it 107b52416c13 bash 
root@107b52416c13:/# mysql -u root -p123456 
Welcome to the MariaDB monitor.  Commands end with ; or \g. 
Your MariaDB connection id is 11 
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
MariaDB [(none)]> 

지금까지 Docker의 기본을 배웠습니다. 더 많은 것을 탐험해 보세요.

Novita AI 는 AI 야망을 실현하는 올인원 클라우드 플랫폼입니다. 원활하게 통합된 API, 서버리스 컴퓨팅, GPU 가속을 통해 AI 기반 비즈니스를 빠르게 구축하고 확장하는 데 필요한 비용 효율적인 도구를 제공합니다. 인프라 문제를 없애고 무료로 시작하세요 - Novita AI는 AI 꿈을 현실로 만듭니다.