1. Introduction

It’s often necessary to guarantee our identity during a connection between devices. SSL certificates are a common way to do this. One certificate contains information about the issuing authority, public key, and expiration date of the certificate.

Virtualization mechanisms, such as Docker containers, are frequently used to execute applications. As a result, we need to import SSL certificates to guarantee secure communication between the application and the client.

In this tutorial, we’ll explore the steps for importing SSL certificates into Docker containers. First, let’s quickly review some concepts and study a code that performs the import. Finally, we’ll run this code in a container environment.

2. Importing SSL Certificates

Containers are isolated environments that encapsulate applications and everything they need to run, ensuring consistency across environments. We use the Dockerfile to build these containers. We need to declare in this file the steps required to build our image, including copying the application project, installing dependencies, and configuring the environment.

To establish secure communication, we must copy the SSL certificate into the container and configure the environment to perform the handshake correctly. Let’s take a look at a Dockerfile snippet that performs this task:

#Dockerfile
FROM your_base_image

# Copy SSL certificates to the container
COPY your_certificate.crt /usr/local/share/ca-certificates/

# Update SSL certificates in the container
RUN update-ca-certificates

In this file, we copy the SSL certificate your_certificate.crt to a directory used by Linux distributions to store implicitly trusted certificates. The update-ca-certificates command updates the certificate store, ensuring that the applications trust the certificate.

It’s important to remember that in these environments, each application will search for SSL certificates in a specific directory within the container. For example, Java applications running on Tomcat usually look for SSL certificates in the $JAVA_HOME/lib/security/cacerts directory.

3. Example

To better understand, let’s build a container with the Dockerfile, copy our SSL certificate, and check that everything went as expected.

As this will be a simple example, we’ll use the Nginx image. Nginx has many features, including an open-source reverse proxy server for HTTP and HTTPS protocols and a load balancer. Also, we created a self-signed certificate using native OpenSSL, named certificate.crt:

#Dockerfile
FROM nginx

# Copy SSL certificates to the container
COPY certificate.crt /usr/local/share/ca-certificates/certificate.crt

# Update SSL certificates in the container
RUN update-ca-certificates

Next, we copy the SSL certificate to the appropriate directory within the container. Emphasizing that in specific cases, a good practice would be to copy the certificate to the directory commonly used by the application to be executed. Then, we update our list of certificates so that the system recognizes the newly added certificate.

Let’s build our container:

$ docker build -t example-certificate .

To confirm that the certificate has been added correctly, we need to run and access the container:

$ docker run example-certificate 
$ docker exec -it 776f315d713f /bin/bash

Note that 776f315d713f is the ID of the running container. To get it, just run the docker ps command and search for the name given to the container. Then, we can list whether the certificate exists in the directory:

$ ls /usr/local/share/ca-certificates | grep certificate.crt
certificate.crt

To view the information on the added certificate, we can use the native OpenSSL:

$ openssl x509 -in /usr/local/share/ca-certificates/certificate.crt -text -noout
Certificate:
    Data:
        Version: 1 (0x0)
        Serial Number:
            1b:dc:b1:66:c0:14:4a:ee:fe:ec:17:21:03:c3:32:6f:df:17:23:ff
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: C = BR, ST = stateA, L = cityA, O = companyA, OU = sectionA, CN = domain, emailAddress = [email protected]
        Validity
            Not Before: Apr 25 17:21:41 2024 GMT
            Not After : Apr 25 17:21:41 2025 GMT
        Subject: C = BR, ST = stateA, L = cityA, O = companyA, OU = sectionA, CN = domain, emailAddress = [email protected]
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
                Public-Key: (2048 bit)
                Modulus:
                    00:b0:ed:ee:1f:bb:58:56:d9:84:f9:75:85:9e:92:
                    f9:bd:a2:d6:8b:51:9e:b5:a4:dd:2e:3b:9a:66:48:
                    bf:6c:5d:8f:74:1d:f9:3d:d2:ae:af:3c:4d:b1:3a:
                    b7:9e:62:ad:8c:6a:8c:b3:da:c9:01:fd:f7:7c:2b:
                    01:31:d9:21:fd:5b:4e:c4:64:e7:d7:24:2a:1f:32:
                    1b:2f:76:37:c3:ab:8d:28:97:3a:77:53:92:bb:c6:
                    a6:44:e4:da:4e:ce:f1:31:69:12:b4:7f:07:61:c8:
                    75:91:8f:6c:72:88:d0:b3:8e:ea:fc:c1:3d:9b:c7:
                    15:a0:cc:37:97:10:c8:0f:41:04:13:c8:0f:0f:71:
                    1d:af:82:76:3c:38:57:91:63:c2:a5:86:e1:36:63:
                    62:04:b3:11:8a:92:16:52:bd:b6:4c:0c:76:cd:48:
                    d4:1d:92:4f:c6:7f:6d:af:33:24:0c:9a:74:a7:ed:
                    8a:99:97:97:28:92:28:99:e5:69:23:0f:46:75:8b:
                    2f:7b:e5:ee:f6:43:cf:a4:4f:c1:a9:5f:b2:3f:d5:
                    ce:aa:36:71:7f:95:48:52:13:50:f6:96:ff:b2:03:
                    3f:8b:9a:0a:d2:20:2d:b2:9c:19:aa:2f:53:4b:a4:
                    c5:bd:fa:9c:54:0a:e9:2d:64:4d:d9:b6:d8:4e:10:
                    3f:71
                Exponent: 65537 (0x10001)
    Signature Algorithm: sha256WithRSAEncryption
    Signature Value:
        39:aa:c0:29:de:0a:8a:23:1c:3e:f7:9b:90:12:a1:5d:fb:91:
        9f:10:23:2c:b9:3f:78:0e:04:b0:ef:60:81:2e:2c:6b:12:ba:
        6d:7c:2f:28:4d:0c:e3:6e:e8:1f:82:a6:f3:57:6d:13:ec:da:
        17:a8:b2:81:63:ab:18:9a:5b:b3:08:9e:9e:a5:51:98:3c:a9:
        3a:fc:01:9c:92:b5:d3:35:54:67:c2:08:29:cb:f3:31:de:af:
        18:6d:13:31:08:82:f6:28:3d:cb:05:ad:1c:bc:8f:1e:3d:4f:
        08:d6:eb:9e:12:32:c0:8c:98:1a:4d:f0:6b:17:82:78:62:cc:
        96:52:ed:2e:b6:f6:81:1f:b6:a2:7e:d7:f3:0b:93:57:11:f1:
        8a:8f:69:fa:b0:f0:61:ce:8d:0a:e5:1b:04:2b:73:bb:c6:80:
        ef:9a:b2:e8:79:a3:16:49:ce:36:46:a9:a1:c2:c7:55:89:9b:
        ef:23:04:96:97:fe:12:a4:7b:2b:ce:42:1d:0d:de:8e:ad:79:
        a2:09:f6:3b:5e:37:eb:f4:c5:2d:56:88:18:73:8b:2b:a7:5c:
        06:e5:24:87:ee:43:75:41:27:46:59:cf:ea:81:07:c1:f3:9a:
        cd:76:26:29:00:63:4d:14:a4:a5:ea:51:42:49:4a:af:54:c9:
        51:ab:69:85

4. Conclusion

In this article, we learned how to import SSL certificates into Docker containers. To achieve this goal, we reviewed the importance of SSL certificates, saw a generic outline for the Dockerfile, and conducted a simple example to learn the complete process.