115

Is there any elegant way to add SSL certificates to images that have come from docker pull?.

I'm looking for a simple and reproducible way of adding a file into /etc/ssl/certs and run update-ca-certificates. (This should cover ubuntu and Debian images).

I'm using docker on CoreOS, and the CoreOS machine trusts the needed SSL certificates, but the docker containers obviously only have the default.

I've tried using docker run --entrypoint=/bin/bash to then add the cert and run update-ca-certificates, but this seems to permanently override the entry point.

I'm also wondering now, would it be more elegant to just mount /etc/ssl/certs on the container from the host machines copy? Doing this would implicitly allow the containers to trust the same things as the host.

I'm at work with an annoying proxy that resigns everything :(. Which breaks SSL and makes containers kind-of strange to work with.

Lii
  • 10,777
  • 7
  • 58
  • 79
Beau Trepp
  • 2,290
  • 3
  • 20
  • 28
  • 3
    Have you thought about creating a Dockerfile that would use your image, add the file and run update-ca-certificates? or is that not what you are looking for? – Céline Aussourd Sep 26 '14 at 14:04
  • 2
    I have done that for some images. It's not a bad solution. Does require you to build on all images with your own though. – Beau Trepp Oct 06 '14 at 00:07

6 Answers6

94

Mount the certs onto the Docker container using -v:

docker run -v /host/path/to/certs:/container/path/to/certs -d IMAGE_ID "update-ca-certificates"
cdrev
  • 5,444
  • 3
  • 19
  • 27
  • 6
    That's pretty nifty. If the container uses the same style of ssl_certs you wouldn't even need the update-ca-certificates line, the host would have already done it :). – Beau Trepp Oct 06 '14 at 00:09
  • 6
    and if we are building in the cloud? – Ewoks Jun 10 '19 at 16:30
  • How does this play nicely with the container images `CMD` or `ENTRYPOINT`. Isn't the "update-ca-certificates" either interpreted as an additional argument or replacing the actual command defined in the Dockerfile? – Joerg Jan 26 '22 at 08:23
31

I am trying to do something similar to this. As commented above, I think you would want to build a new image with a custom Dockerfile (using the image you pulled as a base image), ADD your certificate, then RUN update-ca-certificates. This way you will have a consistent state each time you start a container from this new image.

# Dockerfile
FROM some-base-image:0.1
ADD you_certificate.crt:/container/cert/path
RUN update-ca-certificates

Let's say a docker build against that Dockerfile produced IMAGE_ID. On the next docker run -d [any other options] IMAGE_ID, the container started by that command will have your certificate info. Simple and reproducible.

shudgston
  • 327
  • 3
  • 5
  • Usually I would prefer the docker run -v solution mentioned in other answers. But your solution also works if you need certificates during docker build. Thanks! – bastian Aug 05 '16 at 07:09
  • 18
    I would be wary of putting certificates into any public container. Someone else could pull your container and extract your private certs. – skibum55 Sep 01 '16 at 18:25
  • 7
    While that is a very good point, the solution above does not make anything public. This is meant to add your own certificates into an image that is built locally and then used privately. You _could_ then push the resulting image to a public repository, but that would be a bad idea as you said. – shudgston Sep 26 '16 at 13:58
  • Of course, that image could also be pushed to a private registry too, which is not as bad. – Seer Mar 14 '17 at 12:17
  • 1
    At best this is _okay_. If you want better than okay this sort of configuration needs to be passed in at runtime. In addition to implications about how you will need to store and safeguard the image the same way you would a secret, consider that the certs will eventually expire. If the certs are baked into the image you're effectively setting an expiration of the image which few will be aware of. This is bad. Speaking from experience. – ztech Apr 19 '18 at 15:48
  • 9
    Since when certificates are secret? – techraf Jul 21 '18 at 17:26
  • 8
    Since your server needs a private key to match the certificate it is publishing. – John Rix Apr 03 '19 at 23:38
  • You want to use COPY, not ADD. – jonathan Jun 18 '20 at 14:32
  • @techraf Consider the case of a containerized web app that will connect to RabbitMQ. We want to have server certs on RabbitMQ and client certs in the web app, which it uses to prove "I'm allowed to connect to RabbitMQ", like a username / password but stronger. You may not want to build the client cert into the web app image, as it's meant to be secret. – Nathan Long Oct 13 '20 at 18:20
  • 1
    I wonder how many people got their private cert leaked because of your comment. It's a terrible solution in every way. The least you could do is add a disclaimer to your answer that warns people against making their docker image public if they use your "solution". – MyUsername112358 Feb 11 '22 at 16:00
27

As was suggested in a comment above, if the certificate store on the host is compatible with the guest, you can just mount it directly.

On a Debian host (and container), I've successfully done:

docker run -v /etc/ssl/certs:/etc/ssl/certs:ro ...
Community
  • 1
  • 1
Jonathon Reinhart
  • 124,861
  • 31
  • 240
  • 314
  • 1
    So what to do when building Docker image on the build server? :/ – Ewoks Jun 10 '19 at 16:29
  • @Ewoks You could host your certs on some private DNS and load them inside your helm charts and you can automate creating the volume on your cluster. – Bassam Gamal Sep 12 '19 at 10:48
4

You can use relative path to mount the volume to container:

docker run -v `pwd`/certs:/container/path/to/certs ...

Note the back tick on the pwd which give you the present working directory. It assumes you have the certs folder in current directory that the docker run is executed. Kinda great for local development and keep the certs folder visible to your project.

alltej
  • 5,998
  • 7
  • 39
  • 73
1

I've written a script that wraps docker and sets up the host's SSL certificates in the guest.

The bonus is that you don't need to rebuild any containers - it should Just Work.

It's called docker, so you could either copy it somewhere on your $PATH higher than docker, or rename and put elsewhere.

Do let me know via Github if you have any issues with it!

Ari Fordsham
  • 2,147
  • 6
  • 24
0

This won't directly answer your question but this is how I solved the same issue.

I was running golang:1.16.4-buster and nothing I tried with certificates worked. I switched to golang:1.17.8-alpine3.15 and it worked from the start without having to try to load any certificates. Plus, the bonus of a smaller distro.

Dharman
  • 26,923
  • 21
  • 73
  • 125
Eli Fry
  • 44
  • 5