Installing additional root CA certificates in a Debian-based Node.js Docker container

Posted on Mar 19, 2025

I recently ran into an issue where I couldn’t build or run a Debian-based Docker container on a corporate-issued Windows computer, due to a root CA certificate related to HTTP proxying which wasn’t in the container’s trust store. The Dockerfile for the application contains steps that install additional packages through apt - this would fail because of the untrusted root CA cert in the certification path.

Furthermore, if I used a prebuilt Docker image instead of building it locally, the Node.js runtime would throw errors whenever any HTTPS requests were made.

The application in question uses Debian as its base image - this image can be customised with the root CA certificate (which can be exported from Windows’ certificate store). This is a better solution than disabling certificate validation entirely (e.g. using NODE_TLS_REJECT_UNAUTHORIZED), as it still provides some assurance against a MITM attack or general certificate validation errors that originate outside of the corporate network.

These steps also work exactly the same way on an Ubuntu base image.

Note:

These steps are intended for local development only. Do not publish any Docker images that have been customised with a local root CA certificate, as this presents security risks.


Export the root CA certificate from Windows’ certificate store

  • In certlm.msc, under Trusted Root Certification Authorities\Certificates, find your corporate root certificate.
  • Right click the certificate and select All Tasks -> Export.
  • When asked which file format you want to use, select Base64-encoded X.509 (.CER). Save the file somewhere safe, outside of any Git repositories.

Customise the Dockerfile to trust the new root CA certificate

To trust the certificate under Node.js as well as the rest of the operating system, you need to copy the root CA certificate into the container twice:

  • One file needs to have the .crt extension for update-ca-certificates to pick it up.
  • One file needs to have the .pem extension for use with the NODE_EXTRA_CA_CERTS environment variable.
FROM node:20-bookworm-slim

# Copy the root CA cert into the system trust store.
# Make sure to change the source to point to the local copy of the CA cert.
COPY root-ca.cer /usr/local/share/ca-certificates/root-ca.crt
COPY root-ca.cer /usr/local/share/ca-certificates/root-ca.pem

# Update the list of trusted certificates.
# This step should succeed as long as the apt packages are downloaded via http (true for every base image I tested):
RUN apt update && apt install -y ca-certificates && update-ca-certificates

# Optional: Automatically set the NODE_EXTRA_CA_CERTS environment variable so Node.js trusts the new root CA cert
# If the workload will be run as a non-root user, make sure to change tee's path to the non-root user's bashrc
RUN echo "export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/root-ca.pem" | tee -a /root/.bashrc > /dev/null

# ... any other Dockerfile steps go here

Any HTTPS requests made using the system trust store, or within a Node.js application running in the container, should now succeed.