이미지 빌드 방법으로
이미지를 만드는 방법은 무엇일까?
이미지를 만드는 방법
--
이미지를 만드는 방법에는 크게 2가지가 존재한다.
- 커밋 (commit) : 실행 중인 컨테이너의 상태를 그대로 이미지를 저장한다.
- 빌드 (build) : Dockerfile을 통해서 이미지를 저장한다.
일반적으로 build 방식을 사용하지만
build 방식 또한 commit 방식을 기반으로 동작하기 때문에
commit 방식을 알아 두는 것이 좋다.
--
IaC (Infrastructure as Code) 개념
--
이미지 빌드에 대해 알아보기 전에
먼저 IaC에 대해서 알아야 한다.
IaC는
인프라 구조에서 가장 중요한 개념으로
인프라 상태를 코드로 관리하는 것을 의미한다.
장점
- 일관성 : 모든 인프라 변경 사항이 코드로 관리되므로, 일관성 있는 인프라 환경 유지 가능
- 자동화 : 코드를 통해 인프라 관리 작업의 자동화가 가능
- 복구성 : 코드를 통해 인프라를 재생성하거나 복구 가능 (장애 상황에서 빠르게 복구 가능)
- 테스트와 검증 : 코드를 통해 변경 사항을 테스트하고 검증 가능 (신뢰성 있는 배포 보장)
이미지 빌드가 바로 IaC 방법을 활용해서 코드로 이미지를 관리하는 방식이다.
IaC 방법을 사용하지 않고 서버를 관리하는 예시를 들어보자.
사내 서버 관리자는
회사의 가상 머신을 관리해야 하는데
보통 가상 머신을 관리하는 대시보드를 통해 관리하거나
직접 CLI 명령어를 실행해서 작업을 수행할 수 있다.
발생할 수 있는 문제
- 수동 설정 오류 : 수동으로 서버를 관리하여 설정에 대해 오류가 발생할 수 있음
- 환경 일관성 부족 : 다수의 서버를 수동으로 관리할 경우, 서버 간 환경이 일치하지 않을 수 있음
- 시간 소비 및 오류 : 반복 작업과 인프라 변경 시 시간이 많이 소비
- 배포 지연 : 배포 과정이 길어지고, 신속한 스케일링이 어려울 수 있음
- 추적 및 문서화 어려움 : 인프라의 상태 변경 사항과 구성을 추적하고 문서화가 어려울 수 있음 (유지보수 힘듦)
이때 해당 서버를 관리하는 방법을 잘 모르는 사람이 서버 관리자를 대신하여 서버를 관리하게 되면
전혀 다른 결과가 나오거나 장애가 발생할 위험이 있다.
그래서 IaC 방법을 사용하게 되면 코드로 인프라의 상태를 보다 편리하게 관리할 수 있게 된다.
특정 작업을 수행하는 코드 형식이 정해져 있고 해당 코드의 상세 내용도 기재되어 있다.
그리고 해당 작업은 사람이 직접 CLI로 작업하는 것이 아닌 해당 코드를 가지고 프로그램이 대신 수행해 준다.
그래서 프로그램이 대신 작업을 해주기 때문에 더 빠르고 안전하게 실행할 수 있게 된다.
직접 CLI로 명령어를 작성하는 것과 IaC 방법에서 코드(명령어)를 작성하는 것에 대한 차이가 궁금한데?
똑같이 명령어로 작성하는 거 아니야? 뭐가 다른 거지?
IaC 방법에서 관리자가 코드를 작성하게 되면 컴퓨터(IaC도구)는 해당 코드를 파싱하고 실행을 해준다.
이때 관리자가 작성한 코드를 컴퓨터(IaC도구)가 CLI 명령어나 API 호출을 생성하여 인프라를 관리해 준다.
그래서 코드로 정의된 일관된 방식으로 인프라를 관리할 수 있게 된다.
다만 직접 CLI 명령어를 작성하여 관리하게 되면
코드로 작성하는 방식보다 명령어가 복잡하고 길다.
그러다 보면 명령어 작성 시 실수를 할 수 있게 되고 그러면 예상치 못한 동작을 할 수도 있다.
코드에 들어가는 내용은
프로그램이 작업하기 위한 일련의 작업 명세서로 사용되고
해당 명세서를 GitHub와 같은 소스코드 레포지토리에 저장하게 되면
인프라의 상태도 소스코드처럼 버전 관리를 할 수 있게 된다.
코드는 Dockerfile 파일에 작성한다.
IaC 방법을 활용하는 소프트웨어들이 있지만 도커 또한 IaC 방법을 활용하는 소프트웨어이다.
도커는
Dockerfile 이라는 소스코드 파일을 통해서 인프라의 상태를 저장하는 이미지를 만들 수 있다.
--
도커 build란? ( commit과 build의 차이점 )
--
commit 방식은
이미지를 만들 때마다 컨테이너를 실행해야 하고 명령어를 직접 입력해야 한다.
그리고 커밋 하나당 이미지 레이어가 하나씩 추가되기 때문에
여러 개의 레이어를 추가하고 싶으면 여러 번의 커밋을 해야 한다.
이러한 방식은 복잡하기 때문에 사람이 직접 하게 되면 문제가 발생할 가능성이 커진다.
그래서 도커 이미지를 생성할 때에는 일반적으로 빌드 방식을 많이 사용한다.
build 방식은
컨테이너를 생성하고 커밋하는 것을 docker가 대신 수행해 준다.
즉, commit 방식에서 수행한 과정들을 docker가 알아서 해주는 것이다.
이때 docker에게 어떠한 작업을 수행하게 할지를 코드(명령어)로 작성한 곳이 바로 Dockerfile이라는 소스코드 파일이다.
과정
- 도커가 이해할 수 있는 문법에 따라서 코드를 Dockerfile에 작성
- 도커는 Dockerfile의 내용들을 가지고 임시로 컨테이너를 생성
- 변경사항들을 적용하고 commit 수행 (변경사항을 적용한 이미지 생성)
- 생성했던 임시 컨테이너를 삭제
- Dockerfile에 명시된 내용들을 모두 수행할 때까지 2 ~ 4번을 반복하면서 수행 후 종료된다.
--
build 방식으로 이미지 만들기 (feat. Dockerfile)
--
이미지를 build 하기 전에 Dockerfile부터 작성해야 한다.
Dockerfile에 작성해야 하는 코드(명령어)의 문법은
지시어와 지시어의 옵션으로 구성된다.
우선 가장 기본이 되는 지시어(FROM, COPY, CMD)를 살펴보자.
[FROM] 베이스 이미지 지정하는 명령어 형식 (새롭게 빌드한 이미지에 기반이 되는 이미지를 지정하기)
FROM {이미지명}
베이스 이미지란?
commit 방식으로 이미지를 만들 때에도 처음에 시작점 역할을 하는 이미지(nginx)가 있었다.
이렇게 처음에 시작점 역할을 하는 이미지를 베이스 이미지라고 부른다.
일반적으로 이미지를 빌드할 때 필요한 파일 시스템이 구성되어 있는 이미지를 베이스 이미지로 저장하는 것이 좋다.
예시로
Node.js 애플리케이션을 실행하려면
Node.js가 설치되어 있는 이미지를 베이스 이미지로 선택하는 것이 좋다.
또는 Java 애플리케이션을 실행하려면
Java 런타임이 설치된 이미지를 베이스 이미지로 선택하는 것이 좋다.
Nginx의 1.23 버전을 베이스 이미지로 지정하는 명령어
FROM nginx:1.23
[COPY] 특정 파일을 레이어에 복사하는 명령어 형식
COPY {파일경로} {복사될 대상 경로}
현재 위치에 있는 index.html파일의 내용을 nginx 이미지의 특정 경로에 존재하는 index.html파일에 덮어씌우는 명령어
COPY index.html /usr/share/nginx/html/index.html
/usr/share/nginx 경로 : Nginx 웹 서버가 설치된 경로 (해당 Nginx은 베이스 이미지 Nginx를 가리킨다.)
/usr/share/nginx/html 경로 : Nginx가 제공하는 정적 HTML 파일이 존재하는 기본 디렉터리 경로
/usr/share/nginx/html/index.html 파일 : 웹 서버가 기본적으로 제공하는 HTML 파일
복사될 경로에 작성한 파일(/usr/share/nginx/html/index.html)이 존재한다면
복사할 파일의 내용이 복사될 경로에 있는 파일에 덮어씌우게 되는 것이고
만약 복사될 경로에 작성한 파일(/usr/share/nginx/html/index.html)이 존재하지 않는다면
복사될 경로에 작성한 파일의 명으로 생성되어 복사하게 된다.
즉, COPY 명령어는
복사할 파일의 내용을 지정된 경로에 위치하는 지정된 파일에 복사하는 명령어이고
지정된 경로에 이미 파일이 존재한다면 내용만 덮어씌우고
지정된 경로에 지정한 파일이 존재하지 않는다면 존재하지 않는 파일을 생성하고 복사할 파일의 내용을 덮어씌운다.
{파일경로}는
현재 디렉터리(빌드 콘텍스트) 내의 경로를 기준으로 작성한 경로이고
{복사될 대상 경로}는
Docker 이미지 내의 절대 경로를 기준으로 작성한 경로이다.
[CMD] 컨테이너 실행 시 자동으로 실행될 명령어를 지정하는 명령어 형식 (메타데이터의 Cmd에 작성할 명령어 지정)
CMD {["명령어"]}
컨테이너를 실행할 때 "nginx -g daemon off" 명령어가 실행되도록 지정하는 명령어
CMD ["nginx", "-g", "daemon off;"]
이미지를 빌드하기 전에
터미널에서 위치를 Dockerfile이 존재하는 디렉터리 위치로 이동시켜주어야 한다.
"docker build" 명령어는 Dockerfile이 존재하는 경로에서 작성해야 한다.
다만 꼭 Dockerfile이 존재하는 경로에서 빌드를 해야 하는 것은 아니지만
docker build 명령어를 작성할 때 Dockerfile이 존재하는 경로를 작성해 주어햐 한다.
이때 현재 위치가 Dockerfile이 존재하는 위치면 경로를 작성하기 편해서이다.
현재 위치가 Dockerfile이 존재하지 않는 위치라면 매번 Dockerfile이 존재하는 경로를 작성하는 부분이 달라질 것이다.
Dockerfile이 존재하는 디렉터리의 위치로 이동하는 명령어
cd build/01.buildnginx
이미지를 빌드하는 명령어 형식
docker build -t 이미지명 Dockerfile경로
현재 위치하고 있는 파일들을 통해 이미지를 빌드하는 명령어
docker build -t anijy/buildnginx .
명령어 설명
-t | tag의 약어로 새로 생성될 이미지의 이름을 지정하는 옵션이다. |
. | 현재 위치하고 있는 디렉터리를 의미한다. |
빌드된 이미지를 컨테이너로 실행하는 명령어
docker run -d -p 80:80 --name build-nginx anijy/buildnginx
브라우저 접속하기
--
참고 및 출처
'Docker' 카테고리의 다른 글
Dockerfile의 지시어 정리 (0) | 2024.06.21 |
---|---|
빌드 컨텍스트 (Build Context)란? (0) | 2024.06.20 |
이미지를 만드는(저장) 방법 [ image commit ] (+명령어) (0) | 2024.06.18 |
이미지의 레이어 (Layer) (feat. 컨테이너의 레이어) (0) | 2024.06.17 |
Docker Hub에 이미지 다운로드 및 업로드 명령어 (+ Docker Hub 사용법) (0) | 2024.06.16 |