Docker image는 docker에서 컨테이너 실행을 위해 필요한 모든 파일과 환경 설정들을 포함하고 있는 것을 의미한다.
Docker의 이미지는 Dockerfile에 적힌 명세대로 생성이 된다.
Dockerfile의 구성/작성에 대해서는 이전에 가볍게 정리해보았었다. 👉 docker 이미지 빌드
Dockerfile로 이미지를 빌드할 때에는 한가지 base에 계속 빌드(single stage build)를 진행하거나 여러 단계로 base를 나누어 빌드(multi stage build)를 진행할 수 있다.
FROM
에서 상속 받은 하나의 base image에 모두 진행한 뒤 docker 이미지로 생성해낸다.FROM
에서 상속 받은 base image의 사본들을 생성해 단계별로 사용을 한 뒤, docker 이미지를 만들기 위한 base image에서는 깨끗한 환경에서 package 파일만이 존재할 수 있도록 만들어낸다.multi stage build를 사용한 Dockerfile 예시👇
FROM python:3.7.7-alpine3.12 as base
# stage 1
WORKDIR /usr/src/app
# package build에 필요한 환경 설정
.
.
.
# stage 2
FROM base as builder
# package build에 필요한 dependency, library들 설치
.
.
.
# stage 3
FROM base as final
# package build
COPY --from=builder /venv /venv
COPY --from=builder /usr/src/app/dist .
COPY wsgi.py ./wsgi.py
COPY docker/entrypoint.sh ./entrypoint.sh
ENV PATH="/venv/bin:${PATH}"
RUN . /venv/bin/activate && pip install *.whl
EXPOSE 5000
ENTRYPOINT ["./entrypoint.sh"]
DockerFile를 작성하였다면, 다음과 같은 명령어를 통해 docker file로부터 docker image를 빌드해낼 수 있다.
# context directory : build를 시작하는 dir
# 생성하는 이미지에 tag를 붙이고 싶을 때 -t(tag option) 사용
# tag를 미지정할 경우 자동으로 "lastet"가 붙여짐
$> docker build [-t] <ImageName:TagName> <context directory>
$> docker build .
$> docker build -f <docker 파일 위치>
Docker image는 registry라는 docker를 사용할 수 있도록하는 외부 저장소에 올려놓고 사용할 수 있다.
Registry에 docker image를 push 해두면 사용하고 싶을 때 언제든 가져다 사용할 수 있다.
$> docker build
를 통해 docker image를 빌드하면 기본적으로 docker.io(docker hub) 이름으로 host가 붙여있다고 생각한다.
AWS에서는 ECR(Elastic Container Registry) 라는 별도의 registry를 제공한다.
AWS resource를 사용할 예정이라면 ECR를 사용하는 편이 더 편리할 것이다.
ECR에 docker image를 push하기 위해서는 ECR repo의 주소로 docker image에 이름을 붙여줘야한다.
ECR repo 주소는 {ecr host 주소}/{image 이름}
이고, 이 때 사용하는 ECR의 host 주소는 {aws account}.dkr.ecr.{aws region}.amazonaws.com
로 고정된다.
AWS account의 값은 AWS console을 통해 확인하거나 aws sts get-caller-identity | jq -r .Account
명령어를 통해 cli로 확인할 수도 있다.
$> aws ecr create-reposiotry --repository-name repo이름
$> docker login --username AWS --password-stdin <ecr host 주소>
만약 aws의 username과 password를 모른다면 $> aws ecr get-login-password --region region이름
명령어를 통해 알아올 수 있다.
$> docker push ${ecr repo uri}:${image tag}
위의 과정을 cmd에 하나씩 명령어를 쳐가며 진행을 해도 되지만, shell script로 과정을 작성해두고 script file만 실행시켜서 build 후 push까지 진행한다면 훨씬 간편할 것이다.
build.sh 👇
#!/bin/bash
# 항상 같은 dir에서 실행될 수 있도록 위치를 build를 시작할 위치로 옮겨줌
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )
PROJECT_ROOT=$SCRIPT_DIR
cd "${PROJECT_ROOT}"
AWS_REGION="aws region"
IMAGE_NAME="생성할 docker image 이름"
IMAGE_TAG="latest"
DOCKERCLI=docker
AWSCLI=aws
JQCLI=jq
# build를 진행할 때 필요한 명령어들이 설치되어있는지 여부 확인
# 없어서 error가 발생한다면 종료되도록 setting
set -e
command -v ${AWSCLI} > /dev/null 2>&1 || { echo >&2 'aws-cli not found'; exit 1; }
command -v ${DOCKERCLI} > /dev/null 2>&1 || { echo >&2 'docker not found'; exit 1; }
command -v ${JQCLI} > /dev/null 2>&1 || { echo >&2 'jq not found'; exit 1; }
# setting 해제
set +e
VERSION=$( poetry version -s )
AWS_ACCOUNT_ID=$( ${AWSCLI} sts get-caller-identity | ${JQCLI} -r .Account )
ECR_HOST_NAME=$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
REPO_URI=$ECR_HOST_NAME/$IMAGE_NAME
# 이미지 빌드
${DOCKERCLI} build -t ${IMAGE_NAME} . -f ./Dockerfile
# 빌드한 이미지에 tag 붙이기
# docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
${DOCKERCLI} tag "${IMAGE_NAME}:${IMAGE_TAG}" "${IMAGE_NAME}:${VERSION}"
${DOCKERCLI} tag "${IMAGE_NAME}:${IMAGE_TAG}" "${REPO_URI}:${VERSION}"
${DOCKERCLI} tag "${IMAGE_NAME}:${IMAGE_TAG}" "${REPO_URI}:${IMAGE_TAG}"
# docker가 aws 로그인
aws ecr get-login-password --region $AWS_REGION | \
docker login --username AWS --password-stdin $ECR_HOST_NAME
# docker image push
${DOCKERCLI} push "${REPO_URI}:${VERSION}"
${DOCKERCLI} push "${REPO_URI}:${IMAGE_TAG}"
build.sh를 생성했다면 실행 권한을 추가하고,
$> chmod +x build.sh
실행시킨다.
$> ./build.sh