본문 바로가기

System/Docker

Dockerfile로 도커(Docker) 이미지 빌드 및 컨테이너 생성 기초

반응형

Docker 설치가 완료되면 Dockerfile을 생성하고 빌드할 수 있습니다.

Docker는 내부에 라이브러리 의존성 등을 완전히 포함한 형태이기 때문에 배포가 편리합니다.

우분투 및 CentOS에서 Docker를 설치하는 방법은 아래 링크에서 확인 가능합니다.

2017/09/06 - [System/Docker] - 도커 CE(Docker CE) 우분투 서버에 설치

2017/09/17 - [System/Docker] - 도커 CE(Docker CE) CentOS에 설치

2017/09/18 - [System/Docker] - 리눅스 환경에서 도커 CE(Docker CE) 설치 이후 설정

먼저 Docker의 이미지와 컨테이너라는 용어에 대한 이해가 필요합니다.

이미지는 컨테이너를 실행하기 위한 파일 정보 등을 담고 있습니다.

그리고 이미지를 통해서 실제 실행이 되면 컨테이너라고 부릅니다.

바이너리 실행 파일과 그것을 실행한 프로세서의 관계와 유사한 구조입니다.

Dockerfile은 컨테이너 안에 담길 내용을 담고 있는 설계도라고 할 수 있습니다.

간단하게 Dockerfile을 작성하고 빌드를 통해 이미지를 생성하는 방법을 확인해보겠습니다.

그리고 해당 이미지를 기반으로 컨테이너를 생성해보겠습니다.


1. Dockerfile 정의

Dockerfile은 컨테이너 내부의 구성에 대한 내용을 담고 있습니다.

컨테이너는 격리된 환경에서 동작하기 때문에 외부 네트워크와의 매핑이나 파일의 복사 등이 필요합니다.

먼저 디렉토리를 하나 생성하고 아래 내용으로 Dockerfile을 생성합니다.

Dockerfile

# Use an official Python runtime as a parent image
FROM python:2.7-slim

# Set the working directory to /app
WORKDIR /app

# Copy the current directory contents into the container at /app
ADD . /app

# Install any needed packages specified in requirements.txt
RUN pip install -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

내용은 크게 복잡하지 않은데 FROM, WORKDIR 등 몇 가지 키워드가 사용되고 있습니다.

#으로 처리된 주석 부분의 내용을 참조하면 쉽게 내용을 유추할 수 있습니다.

ADD 명령어를 통해 아래의 두 파일을 ./app 경로에 복사합니다.

그리고 RUN 명령어로 requirements.txt에 정의된 패키지를 설치합니다.

그리고 EXPOSE 명령어를 통해 80번 포트를 외부에서 연결할 수 있게 됩니다.

Dockerfile에서 app.py와 requirements.txt를 참조하고 있는데 해당 파일 역시 생성해야 합니다.

다음과 같은 내용으로 requirements.txt를 생성합니다.

requirements.txt

Flask
Redis

app.py 파일 역시 아래 내용으로 생성합니다.

app.py

from flask import Flask
from redis import Redis, RedisError
import os
import socket

# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)

app = Flask(__name__)

@app.route("/")
def hello():
    try:
        visits = redis.incr("counter")
    except RedisError:
        visits = "<i>cannot connect to Redis, counter disabled</i>"

    html = "<h3>Hello {name}!</h3>" \

           "<b>Hostname:</b> {hostname}<br/>" \
           "<b>Visits:</b> {visits}"
    return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)

if __name__ == "__main__":
    app.run(host='0.0.0.0', port=80)

파이썬으로 작성된 app.py는 Flask를 활용한 간단한 웹페이지입니다.

Dockerfile에 정의된 환경 변수(ENV 부분)인 NAME(기본값 World)을 출력합니다.

그리고 호스트명과 방문자수를 출력하는데 방문자수는 Redis가 없으므로 에러가 발생합니다.


2. 앱 빌드

다음과 같이 모든 파일이 작업 중인 디렉토리 안에 위치하고 있어야 합니다.

이제 build 명령어와 -t 옵션으로 Docker 이미지를 생성합니다.

sudo docker build -t friendlyhello .

명령어 끝의 현재 디렉토리를 의미하는 .반드시 빼지 않고 입력해야 정상적으로 빌드가 진행됩니다.

각 스텝을 1/7 형태로 표시하기 때문에 어떤 작업을 하는지 쉽게 알 수 있습니다.

빌드가 정상적으로 완료되면 생성된 이미지를 확인할 수 있습니다.

sudo docker images

생성한 friendlyhello 이미지가 목록에 표시됩니다.

이미지 자체는 실행된 상태가 아니기 때문에 해당 이미지를 컨테이너로 실행해야 합니다.


3. 컨테이너 생성

컨테이너 생성은 docker의 run 명령어를 사용합니다.

sudo docker run -p 4000:80 friendlyhello

호스트의 4000 포트에 컨테이너 내부의 80 포트를 매핑하기 위해 -p 옵션을 사용합니다.

웹 서버가 동작하게 되는데 4000 포트를 통해서 웹페이지 접속이 가능합니다.

실행 중인 웹 서버를 Ctrl + C를 눌러서 종료합니다.

Docker 컨테이너가 생성되고 실행되면 호스트 역시 입력이 되지 않습니다.

백그라운드에서 daemon 형태로 동작하도록 -d 옵션을 사용할 수 있습니다.

sudo docker run -d -p 4000:80 friendlyhello

긴 컨테이너 ID가 표시되고 이전과 다르게 터미널로 돌아오는 것을 확인할 수 있습니다.

다시 접속해보면 정상적으로 웹페이지가 표시됩니다.


4. 컨테이너 삭제

컨테이너 목록을 확인하기 위해 아래 명령어를 입력합니다.

sudo docker container ls -a

하나는 나중에 실행해서 동작중인 컨테이너이며 다른 하나는 Ctrl + C로 종료한 컨테이너입니다.

컨테이너를 삭제하기 전에 실행 중인 컨테이너는 먼저 중지시켜야 합니다.

sudo docker stop 5903ec0d8212

목록에서 실행중인 컨테이너의 CONTAINER ID를 입력해서 중지시키면 됩니다.

중지된 컨테이너는 rm 명령어로 삭제가 가능합니다.

sudo docker container rm 5903ec0d8212

명령어에서 container를 제외하고 docker rm으로 실행해도 동일하게 동작합니다.


Dockerfile 빌드로 이미지를 생성하는 방법을 확인해봤습니다.

그리고 생성된 이미지를 기반으로 컨테이너를 생성하고 삭제하는 방법 역시 확인할 수 있습니다.

쉘 명령어와 유사한 형태의 명령어를 제공하기 때문에 비교적 쉽게 이해가 가능합니다.

반응형