IT기술/도커 (docker)

Docker 이미지 생성과 배포 완벽 가이드: 컨테이너에서 커스텀 이미지 만들기

후스파 2025. 7. 11. 10:51
반응형

Docker를 사용하여 컨테이너에서 이미지를 만드는 방법에 대해 자세히 알아보겠습니다. 컨테이너 기술은 현대 애플리케이션 개발에서 매우 중요한 역할을 하고 있으며, 이를 통해 우리는 효율적으로 애플리케이션을 배포하고 관리할 수 있습니다. 지금부터 단계별로 설명하겠습니다.


컨테이너로 이미지 만드는 법

Docker에서는 공식적으로 제공되는 이미지를 사용하면 누구나 쉽게 이미지를 만들 수 있습니다. 나만의 이미지를 만들어 동일한 구성의 컨테이너를 대량으로 만들고, 이를 다른 환경에 복제할 수 있는 방법을 배우겠습니다.

이미지 생성의 주요 이점

  • 표준화된 환경: 동일한 설정과 구성을 가진 컨테이너를 여러 환경에서 실행
  • 버전 관리: 애플리케이션의 특정 버전을 이미지로 저장하여 롤백 가능
  • 배포 자동화: CI/CD 파이프라인에서 자동으로 이미지 빌드 및 배포
  • 환경 일관성: 개발, 테스트, 프로덕션 환경 간의 차이 최소화

commit 커맨드

기존 컨테이너를 이미지로 변환하려면 docker commit 명령어를 사용합니다. 이 명령어는 컨테이너의 현재 상태를 기반으로 새로운 이미지를 생성합니다.

# 실행 중인 컨테이너 확인
docker ps

# 모든 컨테이너 확인 (중지된 것 포함)
docker ps -a

출력 예시:

CONTAINER ID   IMAGE     COMMAND              CREATED        STATUS                       PORTS                  NAMES
3e4d91160a3e   httpd     "httpd-foreground"   17 hours ago   Exited (255) 6 minutes ago   0.0.0.0:8181->80/tcp   apaex020
00e7b450ee17   httpd     "httpd-foreground"   17 hours ago   Exited (255) 6 minutes ago   0.0.0.0:8080->80/tcp   apaex010
# 컨테이너를 이미지로 변환
docker commit apaex010 apache_test

실행 결과:

sha256:0e5e0bffb868590840aee05917da1f588d252e8141794c984e13ec16d28ec420

위 예시에서 apaex010이라는 컨테이너를 apache_test라는 이름의 이미지로 변환했습니다. 이후 docker image ls 명령어를 통해 생성된 이미지를 확인할 수 있습니다.

docker image ls

출력 결과:

REPOSITORY                      TAG       IMAGE ID       CREATED         SIZE
apache_test                     latest    0e5e0bffb868   8 seconds ago   178MB
ollama/ollama                   latest    0e59655207b2   6 months ago    536MB
httpd                           latest    062dcbdad052   6 months ago    178MB
ghcr.io/open-webui/open-webui   main      5a6b5ae70d1e   6 months ago    3.12GB

commit 명령어 고급 옵션

# 메시지와 작성자 정보 포함
docker commit -m "Apache server with custom configuration" -a "Developer Name" apaex010 apache_custom:v1.0

# 특정 변경사항만 포함
docker commit --change="ENV DEBUG=true" apaex010 apache_debug:latest

# 포트 노출 설정 추가
docker commit --change="EXPOSE 8080" apaex010 apache_custom:latest

Dockerfile 스크립트

Dockerfile은 이미지를 만드는 데 사용되는 스크립트 파일입니다. 이 파일에는 새로 생성될 이미지의 원본 이미지와 실행할 커맨드 등이 포함됩니다.

Dockerfile 주요 인스트럭션

인스트럭션 설명 예시
FROM 기반이 되는 이미지를 지정합니다 FROM ubuntu:20.04
ADD 이미지에 파일 및 폴더를 추가합니다 ADD app.tar.gz /app/
COPY ADD와 유사하지만, 복사할 경로를 명시적으로 지정합니다 COPY src/ /app/src/
RUN 이미지를 빌드할 때 실행할 명령어를 지정합니다 RUN apt-get update
CMD 컨테이너 실행 시 실행할 명령어를 지정합니다 CMD ["nginx", "-g", "daemon off;"]
ENTRYPOINT 컨테이너 실행 시 강제로 지정할 명령어를 설정합니다 ENTRYPOINT ["/app/start.sh"]
EXPOSE 컨테이너가 사용할 포트를 명시합니다 EXPOSE 80 443
ENV 환경 변수를 정의합니다 ENV NODE_ENV=production
WORKDIR 작업 디렉토리를 설정합니다 WORKDIR /app
USER 실행할 사용자를 지정합니다 USER nginx
VOLUME 마운트 포인트를 생성합니다 VOLUME ["/data"]

아파치 컨테이너 이미지로 변환

아파치 HTTP 서버를 실행하는 컨테이너를 만들고, 이를 이미지로 변환하는 과정을 살펴보겠습니다:

# 아파치 컨테이너 실행
docker run --name apaex030 -d -p 8080:80 httpd

# 컨테이너를 이미지로 변환
docker commit apaex030 apache_ex030

실행 결과:

sha256:fd103f2f0984efa07f7e41f9afb8c491cae2e56a5cd11652a2f3f8e2a46780e8

위의 명령어로 apaex030 컨테이너를 apache_ex030 이미지로 변환했습니다. 이 이미지를 확인해보면 다음과 같습니다:

docker image ls

출력 결과:

REPOSITORY                      TAG       IMAGE ID       CREATED          SIZE
apache_ex030                    latest    fd103f2f0984   11 seconds ago   178MB
ollama/ollama                   latest    0e59655207b2   6 months ago     536MB
httpd                           latest    062dcbdad052   6 months ago     178MB
ghcr.io/open-webui/open-webui   main      5a6b5ae70d1e   6 months ago     3.12GB

Dockerfile 예제

아래는 간단한 Dockerfile 예제입니다. 이 파일은 아파치 서버를 기반으로 하며, index.html 파일을 추가합니다:

기본 Dockerfile

FROM httpd
COPY index.html /usr/local/apache2/htdocs/

고급 Dockerfile 예시

# 멀티 스테이지 빌드 예시
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM httpd:2.4-alpine
LABEL maintainer="developer@example.com"
LABEL version="1.0"
LABEL description="Custom Apache server with Node.js app"

# 보안을 위한 사용자 생성
RUN addgroup -g 1001 -S appgroup && \
    adduser -u 1001 -S appuser -G appgroup

# 필요한 패키지 설치
RUN apk add --no-cache \
    curl \
    bash \
    && rm -rf /var/cache/apk/*

# 애플리케이션 파일 복사
COPY --from=builder /app/dist /usr/local/apache2/htdocs/
COPY ./config/httpd.conf /usr/local/apache2/conf/
COPY ./scripts/entrypoint.sh /usr/local/bin/

# 권한 설정
RUN chmod +x /usr/local/bin/entrypoint.sh && \
    chown -R appuser:appgroup /usr/local/apache2/

# 환경 변수 설정
ENV APACHE_RUN_USER=appuser
ENV APACHE_RUN_GROUP=appgroup
ENV APACHE_LOG_LEVEL=warn

# 포트 노출
EXPOSE 80 443

# 헬스체크 추가
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

# 사용자 변경
USER appuser

# 엔트리포인트 설정
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
CMD ["httpd-foreground"]

이제 Dockerfile을 사용하여 이미지를 생성해보겠습니다:

# 현재 디렉토리의 Dockerfile로 이미지 빌드
docker build -t apache_ex040 .

빌드 과정:

[+] Building 0.1s (7/7) FINISHED                                                                                                              docker:desktop-linux
 => [internal] load build definition from Dockerfile                                                                                                          0.0s
 => => transferring dockerfile: 474B                                                                                                                          0.0s
 => [internal] load metadata for docker.io/library/httpd:latest                                                                                               0.0s
 => [internal] load .dockerignore                                                                                                                             0.0s
 => => transferring context: 2B                                                                                                                               0.0s
 => [internal] load build context                                                                                                                             0.0s
 => => transferring context: 573B                                                                                                                             0.0s
 => [1/2] FROM docker.io/library/httpd:latest                                                                                                                 0.0s
 => [2/2] COPY ./index.html /usr/local/apache2/htdocs                                                                                                         0.0s
 => exporting to image                                                                                                                                        0.0s
 => => exporting layers                                                                                                                                       0.0s
 => => writing image sha256:9f63e4e41f72490668f4dca1ba866ae46925c3a790b3430a32ba4cfbc41d0ebd                                                                  0.0s
 => => naming to docker.io/library/apache_ex040                                                                                                               0.0s

빌드 최적화 팁

# .dockerignore 파일 사용
# .dockerignore
node_modules
.git
.DS_Store
*.log
.env

# 레이어 최적화
RUN apt-get update && \
    apt-get install -y \
        curl \
        vim \
        git && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 캐시 활용을 위한 순서 최적화
COPY package*.json ./
RUN npm install
COPY . .

이미지 옮기는 법

컨테이너를 이미지로 변환하지 않으면 이동이나 복사가 불가능합니다. 이미지를 다른 시스템으로 옮기려면 Docker 레지스트리를 사용하거나, save 명령어로 tar 포맷으로 내보내야 합니다.

이미지 내보내기

# 기본 내보내기
docker save -o 내보내기이미지명.tar 이미지명

# 실제 예시
docker save -o apacheex04.tar apache_ex040

파일 확인:

ll

출력 결과:

total 354960
drwxr-xr-x    5 yunsuhyeon  staff        160  1 24 11:06 .
drwx------@ 313 yunsuhyeon  staff      10016  1 24 10:42 ..
-rw-r--r--@   1 yunsuhyeon  staff         55  1 24 10:58 Dockerfile
-rw-------@   1 yunsuhyeon  staff  181730304  1 24 11:06 apacheex04.tar
-rw-r--r--@   1 yunsuhyeon  staff        126  1 23 17:26 index.html

여러 이미지 동시 내보내기

# 여러 이미지를 하나의 tar 파일로 내보내기
docker save -o multiple_images.tar apache_ex040 nginx:latest mysql:8.0

# 압축하여 내보내기
docker save apache_ex040 | gzip > apache_ex040.tar.gz

이미지 가져오기

다른 시스템에서 이미지를 다시 가져오려면 load 명령어를 사용합니다:

# 기존 이미지 목록 확인
docker image ls

출력 결과:

REPOSITORY                      TAG       IMAGE ID       CREATED        SIZE
ollama/ollama                   latest    0e59655207b2   6 months ago   536MB
httpd                           latest    062dcbdad052   6 months ago   178MB
ghcr.io/open-webui/open-webui   main      5a6b5ae70d1e   6 months ago   3.12GB
# 이미지 가져오기
docker load -i apacheex04.tar

실행 결과:

Loaded image: apache_ex040:latest
# 가져온 이미지 확인
docker image ls

출력 결과:

REPOSITORY                      TAG       IMAGE ID       CREATED         SIZE
apache_ex040                    latest    9f63e4e41f72   6 minutes ago   178MB
ollama/ollama                   latest    0e59655207b2   6 months ago    536MB
httpd                           latest    062dcbdad052   6 months ago    178MB
ghcr.io/open-webui/open-webui   main      5a6b5ae70d1e   6 months ago    3.12GB

이렇게 하면 다시 이미지를 사용할 수 있게 됩니다.


Docker Registry 활용

Docker Hub에 이미지 푸시

# Docker Hub 로그인
docker login

# 이미지 태그 지정
docker tag apache_ex040 username/apache_ex040:v1.0

# 이미지 푸시
docker push username/apache_ex040:v1.0

# 이미지 풀
docker pull username/apache_ex040:v1.0

프라이빗 레지스트리 사용

# 프라이빗 레지스트리 실행
docker run -d -p 5000:5000 --name registry registry:2

# 이미지 태그 지정
docker tag apache_ex040 localhost:5000/apache_ex040:v1.0

# 프라이빗 레지스트리에 푸시
docker push localhost:5000/apache_ex040:v1.0

# 프라이빗 레지스트리에서 풀
docker pull localhost:5000/apache_ex040:v1.0

이미지 최적화 베스트 프랙티스

이미지 크기 최소화

# Alpine Linux 사용
FROM node:18-alpine

# 멀티 스테이지 빌드
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine
COPY --from=builder /app/node_modules ./node_modules
COPY . .
CMD ["node", "server.js"]

보안 강화

# 비root 사용자 사용
FROM alpine:latest
RUN addgroup -g 1001 -S appgroup && \
    adduser -u 1001 -S appuser -G appgroup
USER appuser

# 최신 보안 패치 적용
RUN apk update && apk upgrade && \
    apk add --no-cache curl && \
    rm -rf /var/cache/apk/*

레이어 최적화

# 명령어 체이닝으로 레이어 수 최소화
RUN apt-get update && \
    apt-get install -y \
        curl \
        vim \
        git && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 캐시 효율성을 위한 순서 최적화
COPY package*.json ./
RUN npm install
COPY . .

결론

Docker를 사용하여 컨테이너에서 이미지를 만드는 방법과 Dockerfile의 사용법, 그리고 이미지를 다른 환경으로 옮기는 방법에 대해 알아보았습니다. 이러한 기술들을 활용하면 보다 효율적으로 애플리케이션을 배포하고 관리할 수 있습니다.
핵심 포인트:

  • docker commit 명령어를 통한 컨테이너에서 이미지 생성
  • Dockerfile을 활용한 체계적인 이미지 빌드
  • 멀티 스테이지 빌드를 통한 이미지 크기 최적화
  • docker save/load를 통한 이미지 이동 및 백업
  • Docker Registry 활용으로 이미지 중앙 관리
  • 보안과 성능을 고려한 이미지 최적화

Docker 이미지 생성과 관리를 마스터하면 일관된 개발 환경을 구축하고, CI/CD 파이프라인을 효율적으로 운영할 수 있으며, 마이크로서비스 아키텍처에서 각 서비스를 독립적으로 배포하고 관리할 수 있습니다.

반응형