Intro
Docker Image를 build 할 때 private github repository를 pull하는 등 ssh 인증이 필요한 상황이 있습니다.
ARG SSH_PRIVATE_KEY
RUN mkdir /root/.ssh/
RUN echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa
# something works
RUN rm /root/.ssh/id_rsa
혹시 위와 같은 단순한 방법을 사용하고 있었다면 당장 해당 key를 expire 시켜야 할 수도 있습니다.
필요한 작업을 마친 후 rm
명령어로 해당 ssh key를 지웠다 하더라도 다른 이전 레이어들에 파일의 정보가 그대로 남아있을 수 있고, 무엇보다 ARG
로 전달된 값들은 docker history
명령어 만으로도 그 기록을 모두 확인할 수 있기 때문입니다.
해당 image를 아무곳에도 공개하지 않고 혼자만 쓸 경우에는 괜찮을 수 있지만, 대부분의 경우 그렇지 않고 언제든 실수가 발생할 수 있기 때문에 docker build 에서 안전하고 효율적으로 ssh key를 사용하는 방법을 소개합니다.
- Multi-stage build
- Using ssh with buildkit (recommended)
- Using secret with buildkit
Multi-stage build
Multi-stage build는 하나의 docker file에서 여러개의 docker image를 build 하는 방법입니다.
최종적으로 생성되는 이미지는 그 전에 존재하던 이미지들에 대한 어떠한 정보도 남아있지 않기 때문에, 이 점을 이용하여 안전하게 ssh key를 사용할 수 있습니다.
전체적인 flow와 예시 코드는 아래와 같습니다.
- Image1: Create or copy SSH key → Use SSH key (git clone)
- Image2: Copy cloned repository files from
Image1
→ do your stuff
# Example dockerfile
## Image1: image for clone private repository
FROM ubuntu as intermediate
# 1-1. install git
RUN apt update && apt install git-all -y
# 1-2. add credentials on build (You can pass to ARG or copy from local)
ARG SSH_PRIVATE_KEY
RUN mkdir /root/.ssh/
RUN echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa
# 1-3. add github domain to known hosts
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# 1-4.
RUN git clone git@github.com:<your/private-repo>
## Image2: main image
FROM edvice/torch:v1.12.0-py3.8-cuda11.4-cudnn8-runtime
# 2-1. copy the repository form the previous image name <intermediate>
COPY --from=intermediate </path/of/repo> </dest/of/repo>
# 2~
Run <do your stuff> ...
Multi-stage build를 잘 활용하면 위와 같이 민감한 정보를 숨기거나 Docker image의 크기를 획기적으로 줄이는 등의 효과를 볼 수 있습니다.
Multi-stage build에 대한 자세한 정보는 여기 을 참조해주세요.
What is Docker Buildkit?
Docker buildkit을 사용하면 Multi-stage build보다 더 간단하고 쉽게 ssh key를 사용할 수 있습니다.
Docker buildkit은 docker 18.09 버전 이상에서 사용할 수 있으며 성능, 저장소 관리, 보안 면에서 기존의 builder보다 더욱 우수하고 여러가지 편리하고 강력한 기능들을 추가로 사용할 수 있습니다.
또한 Buildkit으로 만들어진 docker image는 기존의 builder 로 만들어진 image와 완전히 동일하게 사용이 가능하며, docker hub등의 repository에서도 완벽히 호환됩니다.
Docker buildkit을 이용하기 위해서는 docker build 명령어 앞에 DOCKER_BUILDKIT
env를 설정해주면 됩니다.
# ex
$ DOCKER_BUILDKIT=1 docker build .
혹은 /etc/docker/daemon.json
파일을 수정하여 기본값으로 설정할 수 있습니다.
# /etc/docker/daemon.json
{ "features": { "buildkit": true } }
# restart daemon
$ sudo systemctl restart docker
Using ssh with Buildkit
Docker 18.09부터 지원하는 Buildkit의 SSH forwarding
기능을 사용하면 기존의 SSH 인증 정보를 손쉽게 도커 빌드중에도 사용할 수 있습니다.
우선 빌드전에 사용할 SSH key를 SSH-agent에 등록해주는 과정이 필요합니다.
- Run ssh-agent
$ eval $(ssh-agent)
> Agent pid 28899
# Check
$ echo $SSH_AUTH_SOCK
> /tmp/ssh-gE3XpbSmJuAc/agent.28898
- Add ssh key to ssh-agent
$ ssh-add /home/junpyo/.ssh/pyojuncode_ssh/pyojuncode_ssh
이후 SSH forwarding을 사용하기 위해 dockerfile을 구성합니다.
아래 예시의 3번처럼 기존의 명령어 앞에 --mount=type=ssh
를 붙여주시면 됩니다.
# syntax=docker/dockerfile:1
FROM ubuntu:18.04
# 1. Install ssh client and git
RUN apk add --no-cache openssh-client git
# 2. Download public key for github.com
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# 3. Clone private repository
RUN --mount=type=ssh git clone git@github.com:<your/private-repo>
마지막으로 Docker builldkit을 이용하여 Image를 build합니다.
forwarding을 위해 build할 때 --ssh default argument를 추가해야합니다.
$ DOCKER_BUILDKIT=1 docker build --ssh default -t <Image tag> .
해당 이미지에서 Forwarding 된 SSH key를 사용하여 private repository에 성공적으로 접근하고, build 완료 이후에는 SSH key에 대한 그 어떠한 정보도 남아있지 않은것을 확인할 수 있습니다.
추가적으로 id 를 이용하여 여러개의 SSH key를 사용할 수 있습니다.
#In docker file
RUN --mount=type=ssh, id=firstkey git clone ...
RUN --mount=type=ssh, id=secondkey git clone ...
When you run docker build
$ DOCKER_BUILDKIT=1 docker build --ssh firstkey=/path/to/ssh-key --ssh secondkey=/path/to/ssh-key ...
Using secrets with Buildkit
Docker buildkit에 추가된 secret
은 dockerfile 내에서 해당 secret을 mount 한 single-command 에서만 노출되고, 다른 레이어들에서는 전혀 노출되지 않는 특성을 가지고 있습니다.
secret을 mount하면 기본적으로 /run/secrets
폴더에 위치하며 build 시 target
key를 통해 그 위치를 바꿀 수 있습니다.
이 방식을 사용해 기존에 사용하던 SSH-key를 secret으로 마운트하고 사용하는 방법이 있습니다.
# Example
FROM ubuntu:18.04
...
RUN --mount=type=secret, id=githubkey ssh-add /path/to/mounted/key && git clone ...
...
When you build dockerfile
$ DOCKER_BUILDKIT=1 docker build --secret id=githubkey, src=/path/of/local/key ... .
Refs
[https://docs.docker.com/develop/develop-images/build_enhancements/](