이미지는 컨테이너를 실행하기 위한 읽기 전용 파일 입니다.
Docker 이미지는 저장소를 효율적으로 사용하기 위해서 레이어드 파일시스템으로 구성되어 있습니다.
아래 이미지는 Docker Hub와 같은 레지스트리에서 이미지를 다운로드 받는 과정에서의 터미널 화면 입니다.

보는 것과 같이 하나의 이미지를 다운로드 받는 과정에서 pull이 여러 번 실행되는걸 볼 수 있는데, 이때 각각의 한줄이 하나의 레이어를 의미합니다.
이렇게 하나의 이미지를 여러 개의 레이어로 구성한 이유는 이러한 레이어드 구조가 공간을 효율적으로 사용하고 재사용에 용이하기 때문입니다.
이미지의 레이어 특징 중 하나는 “바로 직전 단계의 레이어에서 변경된 내용들만 저장” 한다는 것 입니다.
예를 들어 서버에 간단한 페이지를 출력하는 Nginx를 설치할 경우 이 Nginx를 구성하는 단계는
이제 이 순서대로 이미지의 레이어를 구성한다고 생각해보면
💡 이때, 소프트웨어를 설치하면 OS의 특정 폴더에 Nginx 소프트웨어와 관련된 파일들이 추가됨.
그래서 Nginx를 설치한다는 것은 기존 OS 파일 시스템에서 추가가 되는 부분이 있다는 것을 의미함.
이렇게 기존 레이어에서 변경되는 것들은 이 기존의 레이어를 수정하는게 아니라 기존 레이어 위에 변경된 내용들이 새로운 레이어로 저장됩니다.
다음 특징으로는 이미지에서 한번 저장된 레이어는 변경할 수 없다 입니다.
변경사항이 있으면 위와 같이 새로운 레이어로 저장해야 합니다.
예를 들어 Nginx 설정 파일인 nginx.conf 파일을 작성하거나, index.html 파일의 내용을 수정하는 것도 각각 새로운 레이어로 만들어집니다.
만약 위와 같은 과정을 거쳐서 이미지 A를 만들었다고 가정하고 이번엔 새로운 이미지인 B를 만들어보려 합니다.
그런데 이미지 B는 이전과 똑같은 순서를 거쳐 만들어지지만 마지막 단계에서 index.html 파일의 내용을 이미지 A와는 다르게 작성한다면
이미지 B를 만들 때, Nginx 설정까지는 이미지 A와 모두 같은 레이어를 사용하게 됩니다.
다만, 마지막 index.html 파일에 수정하는 내용이 다르기 때문에 이 마지막 레이어만 새롭게 추가되어서 이미지 B가 완성되게 됩니다.
정리하면 이미지의 레이어 는 순차적으로 쌓이고 각각의 레이어는 이전 레이어에서 변경된 부분을 저장하고 있습니다.
그리고 같은 변경이 일어난 레이어는 공유해서 재사용할 수 있습니다.

출처: 인프런 - 개발자를 위한 쉬운 도커
이제 위 이미지들로 컨테이너를 실행하면 이미지의 가장 마지막 레이어 위에 새로운 읽기 쓰기 전용 레이어가 추가됩니다.
추가된 레이어는 컨테이너 레이어 라고 부릅니다.
애플리케이션에서 로그가 쌓이거나 컨테이너가 실행 중에 생기는 모든 변경사항들은 이 새로운 레이어에 저장됩니다.
읽기 전용인 이미지의 레이어와는 달리 컨테이너 레이어는 이 이미지를 컨테이너로 실행한 다음에 프로세스가 변경하는 내용을 기록하는 레이어로 읽기/쓰기가 모두 가능합니다.
이처럼 컨테이너를 만들고 실행할 때, 사용된 이미지에 따라 이미지의 읽기 전용 레이어 전체를 공유할 수도 있고 일부만 공유할 수도 있는데 이를 활용하면 컨테이너를 실행할 때 전체 공간을 복사하지 않아도 되기 때문에
컨테이너의 실행 속도를 높일 수 있고 컨테이너가 늘어나면서 사용하는 공간을 최대한 효율적으로 관리할 수 있게 됩니다.
# 해당하는 이미지의 레이어 구성 확인
docker image history 이미지명이미지를 만드는 방법엔 크게 2가지가 있습니다.
커밋 방식빌드 방식여기서 대부분 빌드 방식을 사용하지만 이 빌드 방식이 커밋을 기반으로 동작하기 때문에 커밋 방식도 알아두면 도움이 됩니다.
커밋 방식을 사용해서 Nginx 웹서버 이미지를 만들어보기 위해서
컨테이너 레이어 가 만들어지고 수정된 내용이 반영된 것을 볼 수 있습니다.# docker run 명령어를 통해 컨테이너를 실행할 때, -it 옵션을 입력하면 커맨드 창을 통해서
# 실행할 컨테이너와 직접 상호작용 할 수 있음
# -it 옵션을 준 상태에서 cmd의 shell 명령인 bin/bash를 입력하면 기존 cmd 대신 shell을 통해 사용자가 터미널로 접근할 수 있음
docker run -it --name 컨테이너명 이미지명 bin/bash
# 실행 중인 컨테이너의 상태를 새로운 이미지로 저장
docker commit -m 커밋명 실행중인컨테이너명 생성할이미지명💡 IaC 방법론 :
현대 인프라 구성에서 가장 중요한 개념 중 하나로, 인프라를 코드를 통해서 관리한다는 의미.Docker에서도 이 방법론을 활용하여 코드로 이미지를 관리하는 방식이
이미지 빌드
위 커밋 방식은 이미지를 만들 때마다 컨테이너를 실행해야 하고 사용자가 명령어를 직접 입력해야 한다는 단점이 있으며,
커밋 하나당 이미지의 레이어가 하나 추가되기 때문에 여러 개의 레이어를 추가하려면 여러번의 커밋을 수행해야 하는 불편함이 있습니다.
그래서 빌드 방식은 컨테이너를 생성하고 커밋하는 것을 Docker가 대신 수행해 줍니다.
그리고 Docker에게 어떤 작업을 수행할지 코드로 명세한 것이 바로 Dockerfile 입니다.
이렇게 Docker가 이해할 수 있는 문법에 따라서 Dockerfile을 작성하면 Docker는 임시로 컨테이너를 실행하고 사용자가 정의한 작업을 수행한 뒤 커밋을 실행 합니다.
그래서 Docker build를 사용하면 여러 개의 레이어도 쉽게 추가할 수 있습니다.
이미지는 아래 명령어를 통해 빌드할 수 있습니다.
# 도커 파일을 통한 이미지 빌드
docker build -t 이미지명 Dockerfile경로
# 예시) .은 빌드 컨텍스트를 지정
docker build -t examplerepo/buildnginx .
# Dockerfile 명이 Dockerfile 이 아닌 경우에 별도 지정 ( -f 옵션 )
docker build -f 도커파일명 -t 이미지명 Dockerfile경로정리하면, Docker Build는 Docker daemon이 Dockerfile에 적힌 지시어를 사용해서 이미지를 자동으로 만들어주는 방법 입니다.
이미지를 빌드하기 위해서는 문법에 맞게 Dockerfile도 작성해야 합니다.
Dockerfile 문법은 지시어 와 지시어의 옵션 으로 구성됩니다.
⭐️ 기본 지시어
# 새롭게 빌드할 이미지에 기반이 되는 베이스 이미지(필수!)
FROM 이미지명
# 원하는 파일을 레이어에 복사
# 빌드 컨텍스트에 있는 파일을 빌드에 사용되는 컨테이너로 복사
COPY 파일경로 복사할경로
# 컨테이너 안에서 명령어를 실행하고 결과를 새로운 레이어로 저장
RUN 명령어
# 이미지를 컨테이너로 실행할 때, 이 컨테이너 안에서 프로그램을 실행할 명령어 지정
CMD ["명령어"]
# CMD 에서 중복되는 명령어를 지정해서 관리
ENTRYPOINT ["명령어"]RUN 지시어는 새로운 레이어로 저장하는 반면, CMD 지시어는 컨테이너가 실행될 때, 기본 명령어를 지정하기 때문에 별도의 이미지 레이어를 추가하지 않습니다.
⭐️ 시스템 관련 지시어
# 다음 명령어들이 작업할 디렉토리를 지정
# WORKDIR 다음에 나오는 지시어들은 이 WORKDIR에서 지정한 디렉토리를 기준으로 명령어를 수행하기 때문에
# 일반적으로 FROM 지시어 바로 다음에 위치
WORKDIR 폴더명
# USER 지시어는 명령어를 실행할 때 이 명령어를 사용할 기본 사용자를 지정.
USER 유저명
# 컨테이너가 실행할 때 사용할 네트워크 포트를 기재
EXPOSE 포트번호Docker Container가 실행될 때는 기본적으로 명령어들이 루트 사용자로 실행되기 때문에 실행된 프로세스가 굉장히 많은 권한을 가질 수 있다는 보안 유의사항이 있습니다.
그래서 컨테이너가 필요 이상의 권한을 가지지 않도록 USER 지시어로 조절해야 합니다.
⭐️ 환경변수 관련 지시어
# ARG로 지정한 환경변수는 Docker 빌드 명령으로 이미지를 빌드할 때만 사용
ARG 변수명 변수값
# ENV로 지정한 환경변수는 Docker 빌드 뿐만 아니라 이 이미지를 컨테이너로 실행할 때까지 지속적으로 유지
ENV 변수명 변수값빌드 컨텍스트 는 이미지를 빌드할 때, 사용되는 폴더 입니다.
Docker Build 명령을 사용하면 이 빌드 컨텍스트가 Docker daemon에게 통째로 전달됩니다.
그래서 이 컨텍스트 안에 있는 Dockerfile로 Docker daemon이 이미지를 빌드할 수 있는 겁니다.
이 빌드 컨텍스트라는 폴더 내부에는 Dockerfile과 COPY에 사용할 파일들이 모두 들어있어야 합니다.
그리고 빌드 컨텍스트의 .dockerignore 라는 파일을 통해서 빌드 컨텍스트로 전달될 파일을 관리할 수 있습니다.
💡 이미지 빌드 vs 애플리케이션 빌드
애플리케이션 빌드 : 소스 코드를 실행 가능한 상태로 만드는 작업을 의미
이미지 빌드 : 컨테이너로 바로 실행할 수 있는 이미지를 만드는 작업을 의미
멀티 스테이지 빌드는 Dockerfile에서 두 개의 베이스 이미지를 활용하는 방법입니다.
보통 애플리케이션을 빌드하는 과정에서 만들어지는 파일들이 용량을 많이 차지하게 되는데,
이 파일들은 실제로 애플리케이션이 실행되는데는 사용되지 않기 때문에 이미지를 빌드에 사용하는 이미지와 실행에 사용하는 이미지로 나누는 방법을 통해 실제로 애플리케이션이 실행되는 이미지의 크기를 줄일 수 있습니다.
# 첫번째 단계 : 빌드 환경 설정
FROM maven:3.6 AS build
WORKDIR /app
# pom.xml과 src/ 디렉토리 복사
COPY pom.xml .
COPY src ./src
# 애플리케이션 빌드
RUN mvn clean package
# 두번째 단계: 실행 환경 설정
FROM openjdk:11-jre-slim
WORKDIR /app
# 빌드 단계에서 생성된 JAR 파일 복사
COPY /app/target/*.jar ./app.jar
# 애플리케이션 실행
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]이 링크를 통해 구매하시면 제가 수익을 받을 수 있어요. 🤗