About

앞서 작성한 아래 2개의 블로그는 이번 블로그를 위해서 작성된 것이니 혹시나 기본 SSH key를 이용한 서버 접속 및 SSH를 이용하여 private repository를 pip install하는 법을 모르는 분은 보고오시길 바란다.

필자의 회사에서는 좀 더 효율적이고 유연한 코드관리를 위해서 재사용되는 경우가 많은 코드들은 모듈화하여 Private repository로 관리하기 시작했다. 그래서 pip install git+ssh://git@github.com/company_user_id/repo_name.git와 같은 형식으로 설치를 시작하였는데 문제는 Docker Container에는 어떻게 설치해야할지 몰랐다는 것이었다. 무엇보다도 보안의 문제로 SSH_key를 Docker 이미지 빌드과정인 docker history에 남기지않는 방법을 알아내는게 문제였다. 이번 블로그에서는 아래 링크에서 소개된 방법을 번역하여 소개하고자 한다.

Dockerfile

먼저 Dockerfile을 바로 살펴보도록 하자.

# 먼저 intermediate라는 이름으로 우리 목표 image를 만들기전에 private repo들만
# 설치하는 image를 만든다. 여기서 python 버젼은 필요한대로 설정하시길.
FROM python:3.6.6 as intermediate

WORKDIR /tmp
# Build시에 추가한 SSH_PRIVATE_KEY를 추가한다.
ARG SSH_PRIVATE_KEY

# SSH Key를 이용한 서버 접속하는 법을 아시는 분은 아래 명령들은 설명이 필요없을 것이다.
# 만약 이해가 안가는 경우는 위에서 소개한 필자가 작성한 블로그를 확인하길 바란다.
RUN mkdir ~/.ssh/
RUN echo "$SSH_PRIVATE_KEY" >> ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa

# 미리 known_hosts에 등록하여 yes/no를 설치시에 묻는일이 없도록 한다.
RUN touch ~/.ssh/known_hosts
RUN ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

# 우리가 설치할 private_repo정보는 requirements_private_repos.txt에 넣어두자.
COPY ./requirements_private_repos.txt /tmp/
RUN pip install -r requirements_private_repos.txt

# 이제 최종적으로 빌드될 이미지의 환경을 설정한다.
FROM python:3.6.6
# intermediate 이미지에 설치된 private repo들을 copy해온다.
COPY --from=intermediate /usr/local/lib/python3.6/site-packages/ /usr/local/lib/python3.6/site-packages/
ENV PYTHONUNBUFFERED 1

# TODO
# 아래에 나머지 일반적인 Dockerfile 코드를 작성하면된다.

Build dockerfile

이제 위의 Dockerfile을 이용하여 이미지를 빌드하기위한 명령들을 소개하겠다. 위에서 소개한 Medium 블로그에서는 Docker-compose를 사용하여 SSH_PRIVATE_KEY를 전달하였다. 필자는 그냥 Docker build option을 이용하여 진행하고 있으니 두 가지 방법을 다 소개하고자 한다.

  1. Docker-compose

    # docker-compose.yml
    app:
        image: company_name/app:latest
        container_name: app
        env_file:
          - app_env.env
        ports:
          - 8000:8000
        expose:
          - 8000

    여기서 app_env.env라는 파일을 Docker-compose 명령을 실행하는 디렉토리에 넣어두면 되는데 내용은 아래의 형식대로 하면된다.

# app_env.env
SSH_PRIVATE_KEY=ssh-rsa\sdkfjwlek;...

SSH_PRIVATE_KEY라는 변수에 Github과 연결된 ssh private key값을 넣어주면된다. 이 블로그에서는 Docker-compose에 대해서는 자세히 다루지 않을 예정이며 아래에 아주 간단한 명령만 소개하도록 하겠다.

# 위에서 docker-compose.yml은 dockerhub에 올려놓은 
# 회사 앱 이미지를 내려받아서 쓰는 것을 예로 들었으니 pull하는 명령이 먼저 필요하다.
proj-dir$ docker-compose -f docker-compose.yml pull
# Pull 받은 후에 Build 하는 명령이다.
proj-dir$ docker-compose -f docker-compose.yml build --no-cache
# 위의 docker-compose.yml 을 실행한다.
proj-dir$ docker-compose -f docker-compose.yml up
  1. Docker build를 위한 shell script 파일을 만들자.

필자는 매번 SSH_PRIVATE_KEY를 변수로 저장하여 실행하는 번거로움을 피하기위해 이용한 shell script를 소개한다.

#!/bin/bash
# git_ssh.pem은 git에 연결한 ssh private key 값이다.
# 혹시라도 이해가 안가는 분은 위의 링크 중에 github 연결하는 법을 소개한 글을 확인하도록 하자.
export SSH_PRIVATE_KEY="$(cat ~/.ssh/git_ssh.pem)"
# Dockerhub에 업로드할 때 사용할 tag를 입력받는 코드.
echo Insert a docker tag\(latest is default\):
read Tag
export Trimmed_tag="$(echo "$Tag" | tr -d '[:space:]')"
# TODO 사용할 docker_image 이름을 아래에 설정해주자.
export Docker_image_name=""
if [ "$Trimmed_tag" = "" ]; then
  docker build --build-arg SSH_PRIVATE_KEY -t "$Docker_image_name":latest .
  docker push "$Docker_image_name":latest
else
  docker build --no-cache --build-arg SSH_PRIVATE_KEY -t "$Docker_image_name":"$Trimmed_tag" .
  docker push "$Docker_image_name":"$Trimmed_tag"
fi
# 사용을 완료한 변수들은 다 지워준다.
unset SSH_PRIVATE_KEY
unset Docker_image_name
unset Trimmed_tag

Conculusion

docker history에는 최종적으로 사용된 image에 대한 기록만 남기때문에 우리가 private repo를 설치하기위해 사용한 intermediate image에 관한 기록은 남지않게된다. 혹시라도 더 좋은 방법이 있는 분은 아래에 댓글로 남겨주면 정말 감사하겠습니다!