I am trying to make an HTTPS call in a Docker container running a Go binary. This gives me the following error:
x509: failed to load system roots and no roots provided
Having looked this up, it seems the problem is that the BusyBox docker image does not have a root CA certificate. From other answers on StackOverflow it seems that the best approach is to mount the CA root into the /etc/ssl/certs
container directory.
To test locally, it makes sense to mount the host machine's root CA certificate. When running in production (I use Google Container Engine), I'm not sure how to specify a root CA certificate. Do I need to create one myself? Or is there an existing cert in GKE that I can reuse?
There are multiple options you can have
Share certificates from host
As you pointed out you can share /etc/ssl/certs
from the host.
Use busybox with certificates
You can use a image like odise/busybox-curl
which already has the certificates installed.
Use docker-compose and shared volumes for this
This is a better approach as it would not require you to have dependency on host
version: '2'
services:
busybox:
image: busybox
command: sleep 1000
volumes:
- certificates:/etc/ssl/certs:ro
certifcate_installer:
image: alpine
command: sh -c 'apk update && apk add ca-certificates'
volumes:
- certificates:/etc/ssl/certs
volumes:
certificates:
Build it using multi-stage Dockerfile
FROM alpine as certs
RUN apk update && apk add ca-certificates
FROM busybox
COPY --from=certs /etc/ssl/certs /etc/ssl/certs
And then build it like normal file
vagrant@vagrant:~/certs$ docker build -t busyboxcerts .
Sending build context to Docker daemon 49.66kB
Step 1/4 : FROM alpine as certs
---> 4a415e366388
Step 2/4 : RUN apk update && apk add ca-certificates
---> Running in 0059f93b5fc5
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.5/community/x86_64/APKINDEX.tar.gz
v3.5.2-131-g833fa41a4d [http://dl-cdn.alpinelinux.org/alpine/v3.5/main]
v3.5.2-125-g9cb91a548a [http://dl-cdn.alpinelinux.org/alpine/v3.5/community]
OK: 7966 distinct packages available
(1/1) Installing ca-certificates (20161130-r1)
Executing busybox-1.25.1-r0.trigger
Executing ca-certificates-20161130-r1.trigger
OK: 5 MiB in 12 packages
---> 1a84422237e4
Removing intermediate container 0059f93b5fc5
Step 3/4 : FROM busybox
---> efe10ee6727f
Step 4/4 : COPY --from=certs /etc/ssl/certs /etc/ssl/certs
---> af9936f55fc4
Removing intermediate container 1af54c34a5b5
Successfully built af9936f55fc4
Successfully tagged busyboxcerts:latest
vagrant@vagrant:~/certs$ docker run busyboxcerts:latest ls /etc/ssl/certs
02265526.0
024dc131.0
03179a64.0
For more details on multistage build refer to https://docs.docker.com/engine/userguide/eng-image/multistage-build/#before-multi-stage-builds
All methods have their own pros and cons. I would prefer the last or the second last method personally