카테고리 없음

71일차 컨테이너 기술과 Docker (미완)

바론고 2022. 8. 4. 23:16

개발자들은 이와 같이 물자의 수송에 획기적인 단축을 가져다준 컨테이너 기술을 "소프트웨어 수송, 즉 배포에 사용할 수는 없을까?" 하는 생각을 하기 시작했습니다. 그 결과로 리눅스 컨테이너(lxc)라는 것을 만들어내기에 이르렀습니다.

리눅스 컨테이너 기술은 그 자체로 훌륭하고 완성된 기술이었지만, 애플리케이션을 쉽게 컨테이너화할 수 있는 생태계 혹은 커뮤니티가 없었습니다. 2013년에 등장한 도커(Docker)는 바로 Docker Hub라는 소프트웨어 저장소와 함께 빠르게 성장했고, 그 결과 개발자들은 쉽게 애플리케이션을 포장하고, 컨테이너 방식으로 실행할 수 있게 되었습니다.

 

컨테이너 기술의 장점은 한마디로 얘기하면 다음과 같습니다.

실행 환경에 구애받지 않고 애플리케이션을 실행할 수 있다!

이는 달리 얘기하면, 애플리케이션 실행이 어떠한 환경에 구애를 받는다는 말입니다.

 

 

 

왜 Docker 인가? (1)

 

컨테이너 방식의 장점

➡️ 의존성 충돌 문제를 해결해 준다.

  1. 개발과 배포 환경을 일치시킨다.
  2. 수평 확장을 쉽게 해준다.
  3. 각 서버에 새로운 내용을 배포하기 쉽게 만들어준다.


어떤 애플리케이션은, 해당 애플리케이션을 실행하기 위해 반드시 어떤 환경이 구축되어 있어야 합니다. 쉽게는 윈도우용 프로그램을 실행하려면 윈도우 운영체제가 필요하듯 말입니다.

[이미지] 윈도우에서 어떤 애플리케이션을 설치하다 보면, .NET Framework를 설치해야 한다는 문구를 종종 볼 수 있습니다.

우리는 이와 같이 어떤 프로그램(A) 실행에 다른 프로그램(B)이 반드시 필요한 경우, "프로그램 A는 프로그램 B에 의존 관계를 가지고 있다"고 말합니다.

자, 그런데 말입니다, 이러한 경우도 있습니다.

예를 들어, 워드프레스(wordpress)라는 프로그램이, php라는 프로그램에 대해 의존 관계를 가질 때에, 특정 php 버전을 요구하는 경우가 생길 수 있습니다.


그런데 동일한 컴퓨터에 php를 반드시 필요로 하는 drupal이라는 프로그램을 실행시켜야 하는데, 만일 drupal이 php 7 버전이 아닌 6 버전을 사용할 때에만 제대로 작동한다고 가정해 봅시다.


일반적으로 한 컴퓨터에 여러 버전의 동일한 애플리케이션이 설치되지 않으므로, 이 경우에는 php의 의존 관계를 가지고 있는 다른 두 애플리케이션 중에 하나는 제대로 된 실행을 보장할 수 없습니다.

이런 상황을 우리는 "의존성이 충돌한다"라고 말합니다.


컨테이너 기술은 바로 이 문제를 해결합니다. 컨테이너 기술은 애플리케이션컨테이너 내에 구성합니다. 즉, 컨테이너에서 실행 중인 애플리케이션은 어떠한 의존성도 공유하지 않고, 각자 고유의 의존성을 포함하고 있다는 이야기입니다.


이는 각 컨테이너가 철저하게 실행 환경이 격리되어 있기 때문에 가능한 것입니다.


컨테이너는 무엇을 격리하나요?

컨테이너 기술을 바탕으로 한 컴퓨터 안에 여러 대의 컨테이너가 존재하고, 이를 통해 애플리케이션 실행 환경이 격리되어 있음을 앞서 배웠습니다.

하나의 컴퓨터 내에 서로 다른 버전의 php가 설치될 수 있는 것은, 컨테이너 하나하나가 애플리케이션 실행과 관련해서 높은 수준의 격리를 제공하기 때문입니다.

[사진] 컨테이너를 활용한 코로나19 격리 병동 / 출처: https://www.joongang.co.kr/article/23944039#home


그렇다면, 컨테이너는 무엇을 격리하고, 어떤 자원들을 독립적으로 소유할까요? 다음 세 가지를 기억하세요.

  1. 프로세스
  • 특정 컨테이너에서 작동하는 프로세스는 기본적으로 그 컨테이너 안에서만 액세스할 수 있습니다.
  • 컨테이너 안에서 실행되는 프로세스는 다른 컨테이너의 프로세스에게 영향을 줄 수 없습니다.
  1. 네트워크
  • 기본으로 컨테이너 하나에 하나의 IP 주소가 할당되어 있습니다.
  1. 파일 시스템
  • 컨테이너 안에서 사용되는 파일 시스템은 구획화되어 있습니다. 그래서 해당 컨테이너에서의 명령이나 파일 등의 액세스를 제한할 수 있습니다.

컨테이너는 가상 머신인가요?

이러한 기술을 어디선가 보신 분도 있을 겁니다. 바로, 가상 머신(Virtual Machine, 이하 VM)입니다. 하나의 호스트(주인) 컴퓨터 위에 여러 개의 독립적인 컴퓨터가 작동할 수 있게 하는 기술입니다. 이러한 애플리케이션으로는 VMware, VirtualBox, Parallels 등이 있습니다.

[이미지] 윈도우용 Oracle VirtualBox에서 여러 가지의 VM을 실행하고 있습니다. (Windows 8, 10, Ubuntu)


사실, 도커를 비롯한 리눅스 컨테이너 기술은 가상 머신의 접근 방법과는 조금 다릅니다. 이에 대해서는 Self Guided Lessons 에 안내한 "컨테이너와 VM의 비교" 부분에서 보다 더 깊게 다룹니다. 지금은, 컨테이너 역시 가상 머신과 비슷한 수준의 격리성을 제공한다는 정도만 알고 넘어가도 좋습니다.

 

 

 

왜 Docker 인가? (2)

 

컨테이너 방식의 장점

의존성 충돌 문제를 해결해 준다.

  1. ➡️ 개발과 배포 환경을 일치시킨다.
  2. 수평 확장을 쉽게 해준다.
  3. 각 서버에 새로운 내용을 배포하기 쉽게 만들어준다.


개발팀의 문제

Java나 Node.js, Python 등을 이용하여 웹 서비스를 개발하는 개발팀을 상상해 봅시다.

여러 개발자가 하나의 애플리케이션을 만들기 위해, 보통 비슷한 개발 환경을 구축하기 마련입니다.

특정 버전 이상의 JDK, 특정 버전의 MySQL 등을 개발자 각자가 본인의 운영체제에 설치하고, 그 후에 개발을 진행합니다. 하지만 보통의 경우 그 과정이 빠르게 진행되지 않습니다.

애플리케이션을 실행시키기 위해 OS나 JDK, Node.js와 같은 런타임 환경의 버전을 얼추 비슷하게 맞춰야 하는 것은 물론이고, 시스템 환경 변수를 애플리케이션에 맞게 구성해야 제대로 작동하는 경우도 종종 볼 수 있습니다.

리눅스만 하더라도, 배포판에 따라 전혀 다른 애플리케이션 설치 과정이 진행됩니다.

다음은 공식 문서에 있는 우분투에 PostgreSQL을 설치하는 과정입니다.

sudo sh -c 'echo "deb <http://apt.postgresql.org/pub/repos/apt> $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - <https://www.postgresql.org/media/keys/ACCC4CF8.asc> | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install postgresql

반면에, CentOS에서 PostgreSQL을 설치하려면 다음과 같은 과정을 거칩니다.

sudo dnf install -y <https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm>
sudo dnf -qy module disable postgresql
sudo dnf install -y postgresql14-server
sudo /usr/pgsql-14/bin/postgresql-14-setup initdb
sudo systemctl enable postgresql-14
sudo systemctl start postgresql-14

이러한 과정 중에 발생하는 사소한 실수나 사전 설치 항목의 부재는 문제 해결에 많은 시간을 소모하게 합니다. 특히 새로운 프로젝트에 투입되는 개발자의 경우, 그저 애플리케이션을 돌리고 싶었을 뿐인데, 그 길까지 가는 과정이 매우 험난합니다.

도커는 이러한 문제를 해결해 줍니다. 도커가 실행 중이라면, 어떠한 운영체제든 상관없이

다음 명령어즉시 PostgreSQL을 설치하고 실행할 수 있습니다.

docker run --name postgres -e POSTGRES_PASSWORD=mysecret -d postgres

지금이야 단일 소프트웨어 패키지 하나의 사례를 들었지만, 애플리케이션 구성 자체가 컨테이너화되면 (이때 보통 Docker Compose라는 툴을 이용합니다) YAML 파일 하나 + 명령어 하나로 모든 애플리케이션 실행 환경 구성이 완료되는 기적을 볼 수 있습니다.

docker-compose up   # 이후에 실습합니다

따라서 도커는 다음 문제를 해결할 수 있습니다.

  • OS에 상관없이 즉시 애플리케이션 실행 환경을 만들 수 있습니다.
  • 개발을 컨테이너 위에서 진행할 경우, 모든 개발팀이 동일한 환경 하에 개발을 진행할 수 있습니다.

배포 시의 문제

앞서 설명한 실행 및 개발 환경의 일치 이슈는 서비스 배포 환경에서도 동일하게 적용될 수 있습니다. 웹 서비스의 배포란 "어떤 애플리케이션이 특정 런타임 환경 위에서 실행되고, 사용자에게 이를 제공한다"라는 것인데, 이는 앞서 말한 실행 환경 구성과 본질적으로 다를 것이 없기 때문입니다. 그저 서비스를 인터넷상에 공개적으로 노출하느냐, 내 컴퓨터 상에서 프라이빗하게 작동하느냐의 차이일 뿐입니다.

그래서 이제는 배포의 패러다임이 달라졌습니다. 앞서 보았던 선박 그림 기억하시나요? 서버에 파일 하나하나를 업로드하는 방식은 마치 물자를 하나하나 배에 옮기는 이전의 방식이라고 볼 수 있습니다. 서버도 이제는 컨테이너에 담긴 애플리케이션을 실행하는 방식으로 서비스를 제공합니다.

[사진] 하나하나 배에 옮기는 방식
[사진] 컨테이너로 옮기는 방식

따라서 Amazon Web Service의 EC2 상에 도커를 설치하거나, 또는 좀 더 편리하게 도커 컨테이너를 EC2 서버에서 실행할 수 있게 하는 서비스인 ECS를 이용하여 보다 쉽게 애플리케이션을 배포할 수 있습니다.

[이미지] AWS ECS라는 서비스는 애플리케이션을 도커 컨테이너째로 배포할 수 있게 해줍니다.

흔히 이전에 개발자들의 밈(meme) 중 하나였던, "제 컴퓨터에서는 작동되는데요?" 라는 말은 컨테이너 환경에서는 더 이상 유효하지 않습니다.

"제 컴퓨터에서는 작동되는데요? (당신이 잘못했겠지...)"

 

왜 Docker 인가? (3)

 

컨테이너 방식의 장점

의존성 충돌 문제를 해결해 준다.

  1. 개발과 배포 환경을 일치시킨다.
  2. ➡️ 수평 확장을 쉽게 해준다.
  3. ➡️ 각 서버에 새로운 내용을 배포하기 쉽게 만들어준다.


이 콘텐츠는 웹 서비스의 인프라스트럭처에 대한 이해를 바탕으로 합니다. 지금 당장 모든 내용을 이해할 필요는 없지만 가볍게 읽어도 좋습니다.


수평 확장과 새로운 내용의 배포는 한꺼번에 묶어서 설명합니다.


우리가 매일같이 사용하는 글로벌 웹 서비스는 전 세계인들이 사용하므로 그 트래픽이 어마어마합니다. 예를 들어, 지금 이 시간에도 전 세계의 수많은 사람들이 google.com 에 접속할 텐데, 과연 수많은 사람들이 검색 서버라는 단 하나의 컴퓨터에 접속하고 있는 것일까요?

그렇지 않습니다. 서비스 제공자들은 이러한 트래픽 분산을 위해 프록시 서버를 운영하며, 프록시 서버는 여러 대의 동일한 검색 서버 중 한 군데를 이용할 수 있도록 돕습니다. (이러한 서버를 리버스 프록시의 한 종류인 '로드 밸런서'라고 부릅니다)

[이미지] 리버스 프록시 구조 예시

"동일한 서비스가 여러 컴퓨터에서 작동한다"라는 말에서 도커의 필요성을 느꼈다면 이미 여러분은 도커를 이해하고 있는 겁니다.

컨테이너 기술의 가장 큰 장점은 실행 환경의 일치입니다. 더 많은 트래픽으로 인한 서버 증설에 컨테이너 기술은 아주 활발하게 이용되고 있습니다. 동일한 애플리케이션 구성(이미지)을 바탕으로 새로운 서버에 해당 애플리케이션을 컨테이너로 실행하고, 로드 밸런서에 이 서버를 추가하기만 하면 됩니다. (심지어 AWS는 서버를 만들고 삭제하는 일을 자동으로 해줍니다!)

이러한 기술을 응용하여, 새로운 버전의 애플리케이션을 여러 서버 중 몇 대에만 운영하여 테스트하는 방법도 가능합니다. 이를 통해 새 버전의 애플리케이션에서 발생할 수 있는 문제들을 미리 확인하고, 이러한 문제가 사용자 전체에게 영향을 끼치지 않도록 만들 수도 있습니다.

[이미지] 오케스트레이터를 활용한 테스트의 예시

쿠버네티스와 같이 "오케스트레이션 도구"라고 부르는 것들이 이러한 일을 해주는 도구입니다. 이는 결국 컨테이너 기술 덕분에 가능한 것입니다.

 

Docker 핵심 키워드

 

컨테이너

컨테이너는 앞서 설명한 대로, 애플리케이션이 의존성, 네트워크 환경, 파일 시스템에 구애받지 않고, 도커라는 기술 위에 실행될 수 있도록 만든 애플리케이션 상자입니다.

이미지

실행되는 모든 컨테이너는 이미지로부터 생성됩니다. 이미지는 애플리케이션 및 애플리케이션 구성을 함께 담아놓은 템플릿으로, 이를 이용해 즉시 컨테이너를 만들 수 있습니다.

이미지를 이용해 여러 개의 컨테이너를 생성할 수 있습니다. 이를 이용해 앞서 설명한 애플리케이션의 수평 확장이 가능합니다.

이미지는 기본 이미지(base image)로부터 (마치 git을 사용하는 것처럼) 변경 사항을 추가/커밋해서 또 다른 이미지를 만들 수도 있습니다. 예를 들어 스프링부트 기반의 애플리케이션을 이미지로 만들고 싶은 경우, 스프링부트 초기 세팅 이미지를 기본 이미지로 삼고 내가 만든 애플리케이션을 추가해 넣고, 이미지화할 수 있습니다.

레지스트리

이미지는 레지스트리에 저장됩니다. 대표적인 이미지 레지스트리로는 Docker Hub, Amazon ECR이 있습니다. 도커 CLI에서 이미지를 이용해 컨테이너를 생성할 때, 호스트 컴퓨터에 이미지가 존재하지 않는다면, 기본 레지스트리로부터 다운로드 받게 됩니다.

 

 

 

docker/whalesay

docker/whalesay 라는 이미지로 예제를 실습합니다. 먼저, 제공된 이미지를 읽을 수 있어야 합니다.docker/whalesay는 레지스트리 계정, 레포지토리 이름, 태그 세 가지 정보로 구성되어 있습니다.

[그림] 이미지 구분

  • 레지스트리(Registry)
    • Docker Hub : https://hub.docker.com/
    • 도커 이미지를 관리하는 공간입니다.
    • 특별히 다른 것을 지정하지 않는다면, 도커 허브(Docker Hub)를 기본 레지스트리로 설정합니다.
    • 레지스트리는 Docker Hub, Private Docker Hub, 회사 내부용 레지스트리 등으로 나뉠 수 있습니다.
  • 레포지토리(Repository)
    • 레지스트리 내에 도커 이미지가 저장되는 공간입니다.
    • 이미지 이름이 사용되기도 합니다.
    • GitHub의 레포지토리와 유사하게 생각하시면 됩니다.
  • 태그(Tag)
    • 같은 이미지라고 할지라도 버전 별로 안의 내용이 조금은 다를 수 있습니다.
    • 해당 이미지를 설명하는 버전 정보를 주로 입력합니다.
    • 특별히 다른 것을 지정하지 않는다면 latest 태그를 붙인 이미지를 가져옵니다.

docker/whalesay:latest 라는 문장을 다시 읽어보면, 다음와 같이 읽을 수 있습니다.

  • Docker Hub라는 레지스트리에서
  • docker라는 유저가 등록한 whalesay 이미지 혹은 레포지토리에서
  • latest 태그를 가진 이미지

Docker Hub : docker/whalesay

사용할 이미지를 확인했으니, 사용하는 방법을 알아야 합니다. Docker Hub는 Docker Image를 찾거나, Docker Image의 사용방법을 확인할 때 사용할 수 있습니다.

Docker Example 수행하기 : docker/whalesay

[그림] docker/whalesay 이미지 안내 페이지

docker image pull docker/whalesay:latest

[커맨드] docker/whalesay의 최신 이미지를 받아옵니다.

  • [주의!] Ubuntu 운영체제를 통해 실습을 진행하는 수강생분들께서는 모든 명령어 앞에 sudo 명령어를 붙여야 합니다.
  • image pull : 레지스트리에서 이미지 혹은 레포지토리를 가져옵니다.

잠깐! docker pull로 검색해도 많은 정보를 찾을 수 있습니다.

docker image ls

[커맨드] 이미지 리스트를 출력합니다.

  • 받아온 이미지를 실행합니다. (이미지 → 컨테이너)

[그림] 명령어 docker container run 사용법

docker container run --name 컨테이너_이름 docker/whalesay:latest cowsay boo

[커맨드] 컨테이너_이름을 이름으로 갖는 컨테이너를 실행합니다.

  • {container} run
    • 컨테이너를 실행합니다.
  • [OPTIONS]
    • -name : 컨테이너의 이름을 할당합니다.
  • [COMMAND]
    • command는 초기 컨테이너 실행 시 수행되는 명령어입니다.
    • cowsay : 컨테이너 실행 시 cowsay 명령어를 호출합니다. node를 호출하듯 이용합니다.
  • [ARG..]
    • boo : COMMAND인 cowsay에 넘겨질 파라미터입니다.

[그림] 정상적으로 whalesay 컨테이너가 실행되었을 때 터미널에 출력되는 화면

docker container ps -a

[커맨드] 모든 컨테이너의 리스트를 출력합니다.

  • {container} ps : 컨테이너의 리스트를 출력합니다.
  • a : Default 로는 실행되는 컨테이너지만 종료된 컨테이너를 포함하여 모든 컨테이너를 출력합니다.
docker container rm 컨테이너_이름

[커맨드] 컨테이너_이름이라는 이름을 가진 컨테이너를 삭제합니다.

  • {container} rm : 컨테이너를 지칭해서 삭제합니다. 컨테이너를 명시할 때는 ps 명령을 통해 확인할 수 있는 NAMES 혹은 CONTAINER ID 를 사용합니다.
  • 컨테이너 리소스를 지워보고 다시 실행하면서 cowsay 명령어에 매개변수를 변경해 보세요.
    • ex) codestates
    • ex) 자신의 이름

모든 명령을 수행해 보았나요? 그럼 사용한 images의 용량을 확인하고, 도커 이미지를 지워보겠습니다.

# docker image 의 용량 확인
docker image ls

# docker/whalesay 이미지 지우기
docker image rm docker/whalesay

[커맨드] docker image의 용량을 확인하고, docker/whalesay 이미지를 삭제합니다.

다음은 이 콘텐츠에서 사용한 명령어 목록입니다.

  • docker image pull
  • docker image ls
  • docker container run
  • docker container ls
  • docker container rm
  • docker image rm

하나의 이미지를 받아와 컨테이너로 실행하고, 컨테이너와 관련된 리소스를 삭제하는 작업까지 수행했습니다. 이번에는 세 가지 작업을 한 번에 실행해 보겠습니다.

docker container run --name 컨테이너_이름 --rm docker/whalesay cowsay boo

[커맨드] 세 가지 작업을 한 번에 실행하는 명령어

  • {container} run : 컨테이너를 실행합니다. 이미지가 없다면 이미지를 받아온 뒤(pull) 실행합니다.
  • -rm : 컨테이너를 일회성으로 실행합니다. 컨테이너가 중지되거나 종료될 때, 컨테이너와 관련된 리소스를 모두 제거합니다.
docker image rm docker/whalesay

[커맨드] 지정된 도커 이미지를 삭제합니다.

  • image rm : 지정된 도커 이미지를 삭제합니다.

도커는 같은 기능을 수행하더라도, 명령을 여러 형태로 내릴 수 있습니다. 그래서 다른 docker 구문으로 구성된 경우를 만나더라도 명령어가 의미하는 바를 파악할 수 있어야 합니다.

  • docker rmi 도 같은 기능을 수행합니다.

지금까지 잘 진행했다면, 하나의 이미지를 레지스트리에서 받아와서 컨테이너로 실행한 뒤, 사용하지 않는 컨테이너를 지우는 것까지 할 수 있습니다.

Docker Example 수행하기 : danielkraic/asciiquarium

[그림] danielkraic/asciiquarium를 정상적으로 실행시켰을 때 출력되는 알록달록한 바닷속 물고기

danielkraic라는 사람이 올린 이미지 asciiquarium 를 실행합니다.

docker container run -it --rm danielkraic/asciiquarium:latest

[커맨드] danielkraic/asciiquarium 이미지를 실행합니다.

  • it : -i, -t 를 동시에 사용한 옵션입니다. 사용자와 컨테이너 간에 인터렉션(interaction)이 필요하다면 이 옵션을 사용합니다. 이 예제에서는 출력되는 화면을 사용자가 지속적으로 보기 위해서 사용하였습니다. 예를 들어 Python 명령이 필요하거나 추가로 다른 입력을 받는다면, 이 옵션을 지정한 뒤 사용합니다.
  • container는 ctrl + c 로 종료할 수 있습니다.

 

 

 

Docker CLI (2) - Copy, Dockerfile

 

다른 사람이 제공한 도커 이미지를 받아 사용하는 경우, 원하는 모든 기능이 구성되어 있지 않을 수 있습니다. 따라서 이번에는 도커 이미지에 파일을 추가하고, 도커 이미지를 만드는 방법을 학습합니다.

이번 콘텐츠에서는 로컬에 저장된 파일과 함께 도커 이미지를 이용하는 방식을 설명합니다. 또, 로컬 파일과 도커 이미지를 연결하는 방법 중 CP(Copy) 를 이용로컬 파일을 이미지에 복사하고, 팩맨 게임 서버를 실행하는 작업을 수행합니다.

Docker 컨테이너에 파일을 복사하기

앞선 내용에서는 사용할 모든 파일이 하나의 이미지에 구성되어 있고, 그 이미지를 사용하는 방법을 학습했습니다. 그러나 게임 서버, 웹 서버와 같이 여러분이 사용할 도구가 도커 이미지에 모두 구성되어 있지 않은 경우도 있습니다. 예를 들면 다음과 같은 경우입니다.

  1. 웹 서버는 도커 컨테이너로 실행
  2. 웹 서버를 구성하는 파일은 직접 만들거나 가져온 파일 구성
  • 장점
    • 서버에 문제가 생기는 것을 호스트와 별개로 파악할 수 있음
    • 문제가 생긴 서버를 끄고, 마치 공장 초기화를 하듯 도커 이미지로 서버를 재구동할 수 있음

로컬에 있는 파일과 도커 이미지를 연결하는 방법은 크게 CP(Copy) 를 이용하는 방법과 Docker Volume 기능을 이용하는 방법으로 나뉩니다.

  • CP(Copy) : 호스트와 컨테이너 사이에 파일을 복사(Copy)
  • Volume : 호스트와 컨테이너 사이에 공간마운트(Mount)

볼륨과 마운트라는 개념이 생소할 수 있습니다. 간단하게 살펴보면 마운트는 저장 공간을 다른 장치에서 접근할 수 있도록 경로를 허용해서, 마치 하나의 저장 공간을 이용하는 것처럼 보이게 하는 작업을 말합니다. 볼륨 개념과 관련된 레퍼런스 및 실습 과정은 part 2 - 두 개의 Docker Image를 다루는 방식 연습에서 한 번 더 다룹니다.

[그림] 팩맨 파일이 정상적으로 컨테이너로 복사되었을 시 보이는 브라우저 화면

게임 서버 파일은 codestates-seb/be-pacman-canvas 저장소에서 확인할 수 있습니다.

  • 이 레포지토리는 daleharvey/pacman를 기반으로 만들어져 있습니다.

이 파일에는 많은 코드가 작성되어 있지만, 어떻게 작동되는지는 중요하지 않습니다. 서버를 위한 동작, 그림, 사운드 파일이 모두 있다는 사실만 기억하기 바랍니다.

이 동작, 그림, 사운드 파일 모두를 웹 서버에 업로드해서 사용합니다.


httpd 웹 서버

사용할 도커 이미지는 httpd(http daemon)입니다. httpd(http daemon)은 Apache HTTP Server를 실행할 수 있는 오픈소스 웹 서버 소프트웨어입니다.

  • httpd 는 /usr/local/apache2/htdocs/ 경로에 웹 서버와 관련된 파일들이 저장되어 있다면, 해당 파일을 기반으로 웹 서버가 실행되도록 합니다.
  1. codestates-seb/be-pacman-canvas 레포지토리를 클론합니다.[커맨드] be-pacman-canvas 레포지토리를 클론합니다.
  2. 1 2 3 git clone git@github.com:codestates-seb/be-pacman-canvas.git 혹은 git clone https://github.com/codestates-seb/be-pacman-canvas.git
  3. docker container run 명령어로 httpd 를 실행합니다.[커맨드] httpd를 실행합니다.
    [주의] WSL 터미널 혹은 Ubuntu 운영체제를 통해 실습을 진행한다면, 모든 명령어 앞에 sudo 명령어를 붙여야 합니다.
    • run 의 옵션을 docker container run에서 다시 확인할 수 있습니다.
    • -p 옵션은 로컬호스트의 포트와 컨테이너의 포트를 연결합니다. 2의 명령어에서 818포트가 로컬호스트의 포트이고, 80번은 컨테이너의 포트입니다.
    • httpd 는 일정 시간 연결 기록이 없으면, 서버 가동이 중지됩니다. 실행 중이던 도커 컨테이너가 중지되었다면, 다시 실행하세요.
    • 터미널에서 1, 2의 명령어를 입력했을 때, 다음 화면처럼 터미널의 작동이 중단된 것처럼 보여도 걱정할 필요 없습니다. 정상적인 상태이므로 터미널을 종료하지 말고, 다른 터미널 창을 열어 계속해서 실습을 진행합니다.
    [그림] httpd 컨테이너 생성 시 터미널이 위 화면처럼 보이는 것은 정상입니다.
    • 컨테이너를 백그라운드에서 실행하게 해주는 -d 옵션에 대해 알아봅니다. 해당 옵션을 사용했을 때와 사용하지 않았을 때 차이점을 확인해보세요.
  4. 1 docker container run --name 컨테이너_이름 -p 818:80 httpd
  5. 127.0.0.1:818 혹은 localhost:818 을 통해 웹 서버가 작동하고 있는지 확인합니다.
    • 127.0.0.1 과 localhost 를 이용하면 로컬 컴퓨터의 IP 주소로 redirecting 할 수 있습니다. 또, DNS 설정으로 인해 localhost 로 접속이 안 되고 127.0.0.1 만 접속이 될 수 있습니다!
      [그림] httpd 웹 서버 컨테이너가 정상적으로 실행되었을 시 나타나는 브라우저 화면
  6. 서버가 정상적으로 열린 것을 확인한 후, 새로운 터미널을 열어 docker container cp 명령어를 입력해 로컬호스트에 있는 파일을 컨테이너에 전달합니다.
    • 경로를 입력할 때, 상대 경로와 절대 경로를 주의해서 작업하세요!
    • docker container cp 명령은 앞 경로의 파일을 뒤 경로에 복사합니다.
    1
    2
    3
    4
    5
    6
    7
    //지정된 경로에서 명령어를 입력해주세요 
    
    //src/main/resource/template
    docker container cp ./ 컨테이너_이름:/usr/local/apache2/htdocs/
    
    //src/main/resource/static
    docker container cp ./ 컨테이너_이름:/usr/local/apache2/htdocs/
    [커맨드] 현재 폴더의 파일을 뒤 경로에 복사합니다.
    [주의] 위의 명령어를 로컬 터미널에서 실행할 때, 위치는 template, static 디렉토리여야 합니다.
  7. 127.0.0.1:818 혹은 localhost:818 에 접속해서 게임 서버가 구동되는지 확인합니다.

FAQ

  • 컨테이너를 다룰 때, 뭔가 제대로 되지 않는다면 어떻게 그 원인을 알아낼 수 있을까요? docker exec -it 컨테이너_이름 bash 명령어를 통해 컨테이너 내부 터미널로 접속할 수 있습니다. 팩맨 실습에서는 컨테이너 속 '/usr/local/apache2/htdocs' 경로를 잘 살펴보세요.

Docker 이미지 만들기

이번에는 앞서 만들어 본 Docker Container를 이미지 파일로 변환합니다. 이미지로 만들어 놓을 때의 장점은 다음과 같습니다.

  • 이전에 작업했던 내용을 다시 한 번 수행하지 않아도 됨
  • 배포 및 관리가 유용

다음에서 이미지를 만드는 방식 두 가지를 설명합니다.

1. 구동한 Docker Container를 이미지로 만드는 방법

  • docker container commit 명령을 이용[커맨드] 구동한 Docker Container를 commit 합니다.
    [그림] my_pacman 1.0을 확인할 수 있습니다.
  • 1 docker container commit 컨테이너_이름 my_pacman:1.0
  • 생성된 이미지를 900 포트에서 웹 서버로 구동[커맨드] 900 포트에서 웹 서버로 이미지를 구동합니다.
  • 1 docker run --name my_web2 -p 900:80 my_pacman:1.0
  • 127.0.0.1:900 혹은 localhost:900 을 통해 웹 서버가 작동하고 있는지 확인합니다.

2. Docker Image 빌드를 위한 파일인 Dockerfile 로 만드는 방법

Dockerfile의 문법을 모두 공부하고 사용해보는 것도 좋지만, 필요할 때마다 학습하는걸 추천합니다. RUN, CMD, ENTRYPOINT 모두 사용하지 않으면, 헷갈릴 수 있습니다.

  • Dockerfile 공식 문서
    • Dockerfile 을 만들고, Dockerfile 대로 이미지를 build 하는 방법입니다.
  • Dockerfile 은 이미지 파일의 설명서라고 생각하면 좋습니다.
  • Dockerfile로 pacman 이미지를 생성해 보세요.
    • COPY 구문을 잘 살펴보세요. Dockerfile은 어디에 생성되어야 할까요?
    1
    2
    FROM httpd:2.4 # 베이스 이미지를 httpd:2.4 로 사용합니다.
    COPY ./ /usr/local/apache2/htdocs/ # 호스트의 현재 경로에 있는 파일을 생성할 이미지 /usr/local/apache2/htdocs/ 에 복사합니다.
    [코드] 현재 경로에 있는 파일을 생성할 이미지 경로에 복사하는 명령의 Dockerfile 소스 코드입니다.
  • docker build 명령은, Dockerfile로 도커 이미지 파일을 생성합니다.[커맨드] docker build는 Dockerfile로 도커 이미지 파일을 생성합니다.
  • 1 2 3 # --tag 는 name:tag 형식으로 이미지를 생성할 수 있습니다. # 지정한 경로에 있는 Dockerfile을 찾아서 빌드합니다. docker build --tag my_pacman:2.0 . # "."을 명령어에 꼭 포함해야 합니다!
  • 생성된 이미지를 이용해 901 포트에 웹 서버 구동[커맨드] 901 포트에서 웹 서버로 이미지를 구동합니다.
  • 1 docker run --name my_web3 -p 901:80 my_pacman:2.0
  • 127.0.0.1:901 혹은 localhost:901 을 통해 웹 서버가 작동하고 있는지 확인합니다.