Docker & Kubernetes/[Docker]
-
[Docker] 서버에 Dockerfile 생성 후 배포 2023.06.01
[Docker] 서버에 Dockerfile 생성 후 배포
서버 OS 확인
vi /etc/os-release
NAME = "CentOS Linux"
VERSION = "7 (Core)"
Dockerfile
이미지를 만드는 역할
이후 docker run 명령어를 통해 컨테이너로 실행해야 함
1. FROM
FROM 토대가 되는 이미지 지정
서버의 운영 체제와 서버 내에서 실행되는 컨테이너의 운영 체제는 독립적으로 선택할 수 있다.
즉, 서버의 운영 체제가 CentOS7이더라도, 서버 내에서 CentOS8 또는 다른 운영 체제의 컨테이너를 실행할 수 있다.
컨테이너가 자체 파일 시스템, 라이브러리 및 리소스를 가지고 있으므로 서버의 OS와 별도로 관리될 수 있음을 의미한다.
= 서버 OS와 컨테이너 OS 간에 호환성 문제 발생 X
일반적으로는 컨테이너 이미지가 호스트 서버와 유사한 환경을 갖도록 하기위해
서버 OS와 동일하게 설정함
또는 목적에 따라 사용하고자 하는 base 이미지를 사용하면 됨
(ex_ CentOS 서버에서 Python 사용시 CentOS base 이미지를 사용하지 않고 직접 파이썬 이미지 사용 가능)
2. COPY
COPY 이미지에 파일이나 폴더 추가
git repo에 직접 접근하여 코드를 복제(clone)하는 방법이 있다.
하지만 이는 불필요한 보안 문제와 의존성을 야기할 수 있어 권장되지 않는다.
# 권장하지 않음
# Git 저장소 클론을 위한 인증 정보 설정
ARG GIT_USERNAME
ARG GIT_PASSWORD
# 애플리케이션 코드를 복사
WORKDIR /app
RUN git clone https://${GIT_USERNAME}:${GIT_PASSWORD}@<git_repository_url> .
대신, 코드를 Docker 이미지에 직접 복사하는 방식을 사용하는 것이 일반적이다.
1. 서버에 공유 폴더를 생성하고 코드를 해당 폴더에 올려두고 이를 COPY 명령을 사용해 코드를 복사
COPY <호스트(서버)에서 복사할 소스 경로> <복사할 대상 경로>
# ex : 서버에 있는 app.py 코드를 이미지 내부에 /app폴더로 복사
COPY app.py /app/
# ex : src 폴더 내의 모든 파일을 이미지의 /app폴더로 복사
COPY src/* /app/
📌 2. local에 있는 코드를 dockerfile 내에 복사한 후 build 하여 이미지를 만들고
(COPY 경로는 Dockerfile이 있는 디렉토리를 기준으로 상대 경로를 입력)
docker save 명령을 사용해 이미지를 파일로 저장한다.
이후 이미지 파일('.tar')를 서버에 전송해 docker load 명령을 사용해 이미지를 등록하면 된다.
흔히 말하는 "말아올린다"는
일반적으로 소스 코드나 파일을 패키징하여 한 곳에 모으는 작업을 의미한다.
Docker의 경우, Docker 이미지를 빌드할 때 소스 코드나 파일을 이미지 내부로 복사하여 패키징하는 것을 말한다.
이미지 내에 소스 코드를 포함하게 되면 별도로 소스 코드를 압축하고 호스트에 올린 후 압축을 푸는 작업이 생략된다.
하지만 이 경우, 환경변수를 포함한 IP 주소, 포트 번호 등 local 환경에 종속적인 설정은 서버 환경에 맞게 변경해야 한다.
일반적으로 환경변수나 설정 값들은 Dockerfile이나 컨테이너 실행 명령어에서 직접 하드코딩하는 대신,
환경변수를 사용하거나 별도의 설정 파일을 읽어서 동적으로 설정하는 것이 좋다.
이렇게 하면 배포 환경에 따라 설정을 쉽게 변경할 수 있기 때문이다.
3. RUN
RUN 이미지를 빌드할 때 실행할 명령어 지정
컨테이너 내부에서 실행할 명령어를 지정하는 데 사용된다.
예를 들어 아래와 같은 작업을 수행할 수 있다.
패키지 설치 | 파일 다운로드 | 환경 변수 설정 | 소스 코드 빌드 | 파일 복사 | 명령어 실행 | 사용자 추가 | 디렉토리 생성 | 파일 퍼미션 변경 등
RUN 명령어는 컨테이너 이미지를 빌드할 때 실행되며,
이전 단계에서 생성된 파일이나 환경을 기반으로 작업을 진행할 수 있다.
FROM, COPY, RUN 외에도 많은 명령어가 있다.
CMD | 컨테이너를 실행할 때 실행할 명령어 지정 |
ENTRYPOINT | 컨테이너를 실행할 때 실행할 명령어 강제 지정 |
EXPOSE | 이미지가 통신에 사용할 포트를 명시적으로 지정 |
ENV | 환경변수 정의 |
WORKDIR | RUN, CMD, ENTRYPOINT, ADD, COPY에 정의된 명령어를 실행하는 작업 디렉터리 지정 |
ARG | docker build 커맨드를 사용할 때 입력받을 수 있는 인자 선언 |
VOLUME, USER, SHELL 등 더 있지만 생략한다.
CMD와 ENTRYPOINT에 대해 알아보자.
CMD와 ENTRYPOINT는 독립적으로 사용될 수도 있고, 함께 사용될 수도 있다.
독립적 사용
[CMD]
컨테이너 이미지를 실행할 때 기본적으로 실행되는 명령어 정의
docker run 명령어로 컨테이너를 실행할 때 사용자가 추가적인 명령어를 전달하지 않은 경우 실행되는 명령어
[ENTRYPOINT]
컨테이너 이미지를 실행할 때 고정된 명령어 정의
docker run 명령어로 컨테이너를 실행할 때 항상 실행되는 명령어
사용자가 추가적인 명령어를 전달해도 이 명령어 앞 또는 뒤에서 실행됨
함께 사용
[CMD, ENTRYPOINT]
동적으로 실행할 명령어와 인자를 지정
CMD는 ENTRYPOINT의 인자로 사용됨
ENTRYPOINT ["echo", "Hello"]
CMD ["word"]
위와 같이 Dockerfile을 정의한 후
'docker run myimage HiHi' 와 같이 실행하면 컨테이너 내부에서는
'Hello word HiHi'가 실행된다.
예시 Dockerfile (Python, ES, FastAPI)
아래는 CentOS8을 base이미지로 가지고 python, elasticsearch, fastapi를 설치한 후
/app 디렉토리 안에서 app.py 안 app변수 즉 FastAPI 애플리케이션 객체를 실행하는 dockerfile이다.
FROM centos:8
# 기본 패키지 업데이트 및 필수 패키지 설치
RUN dnf update -y && dnf install -y \
curl \
gcc \
openssl-devel \
bzip2-devel \
libffi-devel \
zlib-devel \
make
# Python 3.8 설치
RUN curl -O https://www.python.org/ftp/python/3.8.12/Python-3.8.12.tgz \
&& tar xzf Python-3.8.12.tgz \
&& cd Python-3.8.12 \
&& ./configure --enable-optimizations \
&& make altinstall
# Elasticsearch 7.17.7 설치
RUN rpm --import https://artifacts.elastic.co/GPG-KEY-elasticsearch \
&& echo "name=Elasticsearch Repository for 7.x packages" >> /etc/yum.repos.d/elasticsearch.repo \
&& echo "baseurl=https://artifacts.elastic.co/packages/7.x/yum" >> /etc/yum.repos.d/elasticsearch.repo \
&& echo "enabled=1" >> /etc/yum.repos.d/elasticsearch.repo \
&& echo "gpgcheck=1" >> /etc/yum.repos.d/elasticsearch.repo \
&& dnf install -y elasticsearch-7.17.1
# FastAPI 및 Uvicorn 설치
RUN pip3.8 install fastapi uvicorn
# 작업 디렉토리 생성 및 애플리케이션 코드 복사
WORKDIR /app
COPY app.py .
# 컨테이너 실행 명령어 설정
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
앞선 언급한 바와 같이 base이미지를 centOS가 아닌 Python을 사용해도 된다.
FROM python:3.8
# 기본 패키지 업데이트 및 필수 패키지 설치
RUN apt-get update && apt-get install -y \
curl \
gcc \
libssl-dev \
libbz2-dev \
libffi-dev \
zlib1g-dev \
make
# Elasticsearch 7.17.7 설치
RUN curl https://artifacts.elastic.co/GPG-KEY-elasticsearch | apt-key add - \
&& echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elasticsearch.list \
&& apt-get update \
&& apt-get install -y elasticsearch=7.17.1
# FastAPI 및 Uvicorn 설치
RUN pip install fastapi uvicorn
# 작업 디렉토리 생성 및 애플리케이션 코드 복사
WORKDIR /app
COPY app.py .
# 컨테이너 실행 명령어 설정
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
도커 파일을 만들어서 서버에 배포하는 방법을 요약하자면 아래와 같다.
1. local 환경에서 dockerfile 내에 소스 코드를 포함하여 이미지 빌드
docker build -t 생성할_이미지_이름 재료_폴더_경로
2. docker save를 통해 빌드한 이미지를 파일(.tar)로 변경
docker save -o 이미지_파일.tar 이미지_이름:태그
3. 이미지 파일을 서버에 전송 후 docker load를 통해 이미지 등록
docker load -i 이미지_파일.tar
4. docker run을 통해 등록한 이미지로 컨테이너 생성 및 실행
docker run (옵션) 이미지_이름_태그