9

I have the following Dockerfile:

FROM ubuntu:16.04

RUN apt-get update \
    && apt-get upgrade -y \
    && apt-get install -y \
    git \
    make \
    python-pip \
    python2.7 \
    python2.7-dev \
    ssh \
    && apt-get autoremove \
    && apt-get clean

ARG password
ARG username
ENV password $password
ENV username $username

RUN pip install git+http://$username:$password@org.bitbucket.com/scm/do/repo.git

I use the following commands to build the image from this Dockerfile:

docker build -t myimage:v1 --build-arg password="somepassoword" --build-arg username="someuser" .

However, in the build log the username and password that I pass as --build-arg are visible.

Step 8/8 : RUN pip install git+http://$username:$password@org.bitbucket.com/scm/do/repo.git
 ---> Running in 650d9423b549
Collecting git+http://someuser:somepassword@org.bitbucket.com/scm/do/repo.git

How to hide them? Or is there a different way of passing the credentials in the Dockerfile?

ANIL
  • 2,542
  • 4
  • 25
  • 44

3 Answers3

5

Update

You know, I was focusing on the wrong part of your question. You shouldn't be using a username and password at all. You should be using access keys, which permit read-only access to private repositories.

Once you've created an ssh key and added the public component to your repository, you can then drop the private key into your image:

RUN mkdir -m 700 -p /root/.ssh
COPY my_access_key /root/.ssh/id_rsa
RUN chmod 700 /root/.ssh/id_rsa

And now you can use that key when installing your Python project:

RUN pip install git+ssh://git@bitbucket.org/you/yourproject.repo

(Original answer follows)

You would generally not bake credentials into an image like this. In addition to the problem you've already discovered, it makes your image less useful because you would need to rebuild it every time your credentials changed, or if more than one person wanted to be able to use it.

Credentials are more generally provided at runtime via one of various mechanisms:

  • Environment variables: you can place your credentials in a file, e.g.:

    USERNAME=myname
    PASSWORD=secret
    

    And then include that on the docker run command line:

    docker run --env-file myenvfile.env ...
    

    The USERNAME and PASSWORD environment variables will be available to processes in your container.

  • Bind mounts: you can place your credentials in a file, and then expose that file inside your container as a bind mount using the -v option to docker run:

    docker run -v /path/to/myfile:/path/inside/container ...
    

    This would expose the file as /path/inside/container inside your container.

  • Docker secrets: If you're running Docker in swarm mode, you can expose your credentials as docker secrets.

larsks
  • 277,717
  • 41
  • 399
  • 399
  • Yes you are right but I need to clone and pip install my Python project while building the image, so whenever my image is run the container should have the package installed. Are you suggesting that I should use CMD instead of RUN so I can pass an --env-file when I build the container from my image? – ANIL Jan 10 '19 at 12:23
  • So, it should be the public_key of the system from where I want to access my repo right? In this case it is going to be my system from where I am going to build my image? So, I should create a RSS key-pair and add the public-key to the repo and copy the private-key into the container? – ANIL Jan 10 '19 at 13:23
5

It's worse than that: they're in docker history in perpetuity.

I've done two things here in the past that work:

You can configure pip to use local packages, or to download dependencies ahead of time into "wheel" files. Outside of Docker you can download the package from the private repository, giving the credentials there, and then you can COPY in the resulting .whl file.

pip install wheel
pip wheel --wheel-dir ./wheels git+http://$username:$password@org.bitbucket.com/scm/do/repo.git
docker build .
COPY ./wheels/ ./wheels/
RUN pip install wheels/*.whl

The second is to use a multi-stage Dockerfile where the first stage does all of the installation, and the second doesn't need the credentials. This might look something like

FROM ubuntu:16.04 AS build
RUN apt-get update && ...
...
RUN pip install git+http://$username:$password@org.bitbucket.com/scm/do/repo.git

FROM ubuntu:16.04
RUN apt-get update \
 && apt-get upgrade -y \
 && apt-get install \
      python2.7
COPY --from=build /usr/lib/python2.7/site-packages/ /usr/lib/python2.7/site-packages/
COPY ...
CMD ["./app.py"]

It's worth double-checking in the second case that nothing has gotten leaked into your final image, because the ARG values are still available to the second stage.

David Maze
  • 130,717
  • 29
  • 175
  • 215
0

For me, I created a bash file call set-up-cred.sh.

Inside set-up-cred.sh

echo $CRED > cred.txt;

Then, in Dockerfile,

RUN bash set-up-cred.sh;
...
RUN rm cred.txt;

This is for hiding echoing credential variables.

  • This is surely a bad thing to do. cred.txt is going to exist in the layers, unless perhaps you squash them. Far better to use the --secret feature of the buildkit (need to use "docker buildx build", not just "docker build") to pass the password. You can use GIT_ASKPASS to avoid the password appearing in the history. See (perhaps) https://pythonspeed.com/articles/docker-build-secrets/ – johnfo Nov 26 '22 at 09:49