Using SSH keys inside docker container

2019-01-03 07:35发布

I have an app that executes various fun stuff with Git (like running git clone & git push) and I'm trying to docker-ize it.

I'm running into an issue though where I need to be able to add an SSH key to the container for the container 'user' to use.

I tried copying it into /root/.ssh/, changing $HOME, creating a git ssh wrapper, and still no luck.

Here is the Dockerfile for reference:

#DOCKER-VERSION 0.3.4                                                           

from  ubuntu:12.04                                                              

RUN  apt-get update                                                             
RUN  apt-get install python-software-properties python g++ make git-core openssh-server -y
RUN  add-apt-repository ppa:chris-lea/node.js                                   
RUN  echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list
RUN  apt-get update                                                             
RUN  apt-get install nodejs -y                                                  

ADD . /src                                                                       
ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa                             
RUN   cd /src; npm install                                                      

EXPOSE  808:808                                                                 

CMD   [ "node", "/src/app.js"]

app.js runs the git commands like git pull

22条回答
对你真心纯属浪费
2楼-- · 2019-01-03 08:09

One solution is to mount host's ssh keys into docker with following options:

docker run -v /home/<host user>/.ssh:/home/<docker user>/.ssh <image>

Similar to above solution. But works with a non root user. Work perfectly with github.

查看更多
乱世女痞
3楼-- · 2019-01-03 08:10

In later versions of docker (17.05) you can use multi stage builds. Which is the safest option as the previous builds can only ever be used by the subsequent build and are then destroyed

See the answer to my stackoverflow question for more info

查看更多
ら.Afraid
4楼-- · 2019-01-03 08:11

Expanding Peter Grainger's answer I was able to use multi-stage build available since Docker 17.05. Official page states:

With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.

Keeping this in mind here is my example of Dockerfile including three build stages. It's meant to create a production image of client web application.

# Stage 1: get sources from npm and git over ssh
FROM node:carbon AS sources
ARG SSH_KEY
ARG SSH_KEY_PASSPHRASE
RUN mkdir -p /root/.ssh && \
    chmod 0700 /root/.ssh && \
    ssh-keyscan bitbucket.org > /root/.ssh/known_hosts && \
    echo "${SSH_KEY}" > /root/.ssh/id_rsa && \
    chmod 600 /root/.ssh/id_rsa
WORKDIR /app/
COPY package*.json yarn.lock /app/
RUN eval `ssh-agent -s` && \
    printf "${SSH_KEY_PASSPHRASE}\n" | ssh-add $HOME/.ssh/id_rsa && \
    yarn --pure-lockfile --mutex file --network-concurrency 1 && \
    rm -rf /root/.ssh/

# Stage 2: build minified production code
FROM node:carbon AS production
WORKDIR /app/
COPY --from=sources /app/ /app/
COPY . /app/
RUN yarn build:prod

# Stage 3: include only built production files and host them with Node Express server
FROM node:carbon
WORKDIR /app/
RUN yarn add express
COPY --from=production /app/dist/ /app/dist/
COPY server.js /app/
EXPOSE 33330
CMD ["node", "server.js"]

.dockerignore repeats contents of .gitignore file (it prevents node_modules and resulting dist directories of the project from being copied):

.idea
dist
node_modules
*.log

Command example to build an image:

$ docker build -t ezze/geoport:0.6.0 \
  --build-arg SSH_KEY=$(cat ~/.ssh/id_rsa) \
  --build-arg SSH_KEY_PASSPHRASE=my_super_secret \
  ./

If your private SSH key doesn't have a passphrase just specify empty SSH_KEY_PASSPHRASE argument.

This is how it works:

1). On the first stage only package.json, yarn.lock files and private SSH key are copied to the first intermediate image named sources. In order to avoid further SSH key passphrase prompts it is automatically added to ssh-agent. Finally yarn command installs all required dependencies from NPM and clones private git repositories from Bitbucket over SSH.

2). The second stage builds and minifies source code of web application and places it in dist directory of the next intermediate image named production. Note that source code of installed node_modules is copied from the image named sources produced on the first stage by this line:

COPY --from=sources /app/ /app/

Probably it also could be the following line:

COPY --from=sources /app/node_modules/ /app/node_modules/

We have only node_modules directory from the first intermediate image here, no SSH_KEY and SSH_KEY_PASSPHRASE arguments anymore. All the rest required for build is copied from our project directory.

3). On the third stage we reduce a size of the final image that will be tagged as ezze/geoport:0.6.0 by including only dist directory from the second intermediate image named production and installing Node Express for starting a web server.

Listing images gives an output like this:

REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ezze/geoport        0.6.0               8e8809c4e996        3 hours ago         717MB
<none>              <none>              1f6518644324        3 hours ago         1.1GB
<none>              <none>              fa00f1182917        4 hours ago         1.63GB
node                carbon              b87c2ad8344d        4 weeks ago         676MB

where non-tagged images correpsond to the first and the second intermediate build stages.

If you run

$ docker history ezze/geoport:0.6.0 --no-trunc

you will not see any mentions of SSH_KEY and SSH_KEY_PASSPHRASE in the final image.

查看更多
趁早两清
5楼-- · 2019-01-03 08:13

Turns out when using Ubuntu, the ssh_config isn't correct. You need to add

RUN  echo "    IdentityFile ~/.ssh/id_rsa" >> /etc/ssh/ssh_config

to your Dockerfile in order to get it to recognize your ssh key.

查看更多
霸刀☆藐视天下
6楼-- · 2019-01-03 08:14

If you are using docker compose an easy choice is to forward SSH agent like that:

something:
    container_name: something
    volumes:
        - $SSH_AUTH_SOCK:/ssh-agent # Forward local machine SSH key to docker
    environment:
        SSH_AUTH_SOCK: /ssh-agent
查看更多
贪生不怕死
7楼-- · 2019-01-03 08:16

This line is a problem:

ADD ../../home/ubuntu/.ssh/id_rsa /root/.ssh/id_rsa

When specifying the files you want to copy into the image you can only use relative paths - relative to the directory where your Dockerfile is. So you should instead use:

ADD id_rsa /root/.ssh/id_rsa

And put the id_rsa file into the same directory where your Dockerfile is.

Check this out for more details: http://docs.docker.io/reference/builder/#add

查看更多
登录 后发表回答