Skip to main content

Docker Deployment

Add CertOne to your application image to obtain certificates before starting the application. Subsequent update notifications trigger certificate replacement and application reloads. You can use the application image version you need.

This guide configures environment variables directly in the Dockerfile and provides a complete nginx example. No separate environment file is needed. Complete httpd and OpenResty variants are provided below. For Caddy, HAProxy, and Mosquitto, see More Docker Services. For other images and entrypoints, see Custom Images.

Prerequisites​

  • Docker is installed, and the machine can reach the platform and download endpoint.
  • You have created a deployment node, associated issued certificates, and obtained its node ID and Token.
  • You have chosen the application image version, HTTPS configuration, and service ports.

These examples run as root inside the container and use /root/.certone. For a non-root image, first adjust paths and permissions as described under Runtime User and Directories.

1. Prepare the Dockerfile​

Save the nginx example below as Dockerfile. Choose the base image version you need. For httpd or OpenResty, use the corresponding example under Other application images.

The Dockerfile downloads and verifies CertOne, preserves the standard image's original entrypoint, and prepares certificates before starting the application. Set the node ID and Token in the ENV lines below.

FROM alpine:3.23 AS certone-download
RUN apk add --no-cache curl ca-certificates
RUN curl -fsSL https://certone.io/downloads/certone/install.sh -o /tmp/install.sh \
&& CERTONE_INSTALL_DIR=/out sh /tmp/install.sh

FROM nginx:stable
COPY --from=certone-download /out/certone /usr/local/bin/certone
COPY site.conf /etc/nginx/conf.d/default.conf
STOPSIGNAL SIGTERM
ENV CERTONE_NODE_ID="node-REPLACE"
ENV CERTONE_TOKEN="REPLACE_WITH_NODE_TOKEN"
ENV CERTONE_DEPLOY_TYPE=nginx
ENTRYPOINT ["/usr/local/bin/certone","exec","--env","--","/docker-entrypoint.sh"]
CMD ["nginx","-g","daemon off;"]

Replace nginx:stable as needed. Prepare site.conf in step 3; the Dockerfile already copies it into the image.

2. Configure the connection​

In the Dockerfile from step 1, replace node-REPLACE and REPLACE_WITH_NODE_TOKEN with the node ID and Token copied from the platform. Keep the surrounding double quotes. The agent automatically discovers all certificates associated with the node; you do not need to specify them individually.

Keep the image private

The Dockerfile and built image contain the node Token. Anyone with access to either can read it. Keep both private and do not publish them to a public repository or image registry. For a shared image, supply credentials at runtime instead.

CERTONE_DEPLOY_TYPE supplies preset validation and reload commands for supported applications. For custom commands and certificate directories, see the Environment Variable Reference.

Each certificate is saved in its own directory, named after its certificate ID. Replace cert-REPLACE below with the ID of the certificate used by the website. You can find it in the platform or the deployment logs. This path tells the application which files to read; it does not filter which certificates the agent synchronizes.

3. Configure HTTPS certificate paths​

Default file locations:

FilePath inside the container
Full certificate chain/root/.certone/certificates/cert-REPLACE/fullchain.pem
Private key/root/.certone/certificates/cert-REPLACE/key.pem

Enable HTTPS in your application and reference these files. For an existing nginx website, update ssl_certificate and ssl_certificate_key. This minimal site.conf can be used to verify the first deployment:

server {
listen 443 ssl;
server_name example.com;
ssl_certificate /root/.certone/certificates/cert-REPLACE/fullchain.pem;
ssl_certificate_key /root/.certone/certificates/cert-REPLACE/key.pem;

location / {
return 200 "HTTPS is ready\n";
}
}

Replace example.com with a domain covered by the certificate. Preserve your application's routing and other settings when updating an existing configuration. The Dockerfile in step 1 already copies this file into nginx.

Before building, the working directory should contain Dockerfile and site.conf. Also create .dockerignore containing the following to exclude unrelated local credentials and state from the build context. This does not remove the Token configured in the Dockerfile from the image:

.env
.certone/
certone/

httpd and OpenResty use their own HTTPS configuration syntax and file locations.

4. Build and start​

docker build -t my-app-certone .
docker run -d --name my-app --init --restart unless-stopped \
-p 443:443 \
--log-opt max-size=10m --log-opt max-file=5 \
-v certone-data:/root/.certone my-app-certone

certone-data stores the entire agent directory, including certificates, instance identity, cache, and recovery records. Keep using this volume when upgrading or recreating the container. Use a separate volume for each replica.

The first startup must successfully obtain certificates from the platform before the application starts. An explicit authentication rejection prevents application startup. Correct the ENV values in the Dockerfile, rebuild the image, and recreate the container with the same data volume. Restarting the old container does not apply Dockerfile changes.

5. Verify the deployment​

docker logs --tail 100 my-app
docker exec my-app certone status --env

Confirm all of the following:

  1. Logs show successful certificate deployment and application startup.
  2. certone status --env shows the expected deployed versions and a recent state timestamp.
  3. The actual HTTPS endpoint serves the expected certificate.

If startup fails, use docker logs --tail 100 my-app first. For a container that stays running, docker exec my-app certone doctor --network --env checks authentication and lists available certificates without deploying. If the container exits, validate the settings using a disposable container: docker run --rm --entrypoint certone my-app-certone check --env.

A running container does not prove that the certificate is active. See Troubleshooting to check authentication, output files, application reloads, and the endpoint you are visiting.

Other application images​

Use the same data volume, build/run commands and verification steps above. Fill in the node ID and Token directly in the chosen Dockerfile. Replace the nginx Dockerfile and site.conf with one matching pair below. Replace example.com and cert-REPLACE in the configuration with your domain and certificate ID.

httpd​

Dockerfile:

FROM alpine:3.23 AS certone-download
RUN apk add --no-cache curl ca-certificates
RUN curl -fsSL https://certone.io/downloads/certone/install.sh -o /tmp/install.sh \
&& CERTONE_INSTALL_DIR=/out sh /tmp/install.sh

FROM httpd:2.4
COPY --from=certone-download /out/certone /usr/local/bin/certone
RUN sed -i 's/^#LoadModule ssl_module/LoadModule ssl_module/;s/^#LoadModule socache_shmcb_module/LoadModule socache_shmcb_module/' /usr/local/apache2/conf/httpd.conf \
&& printf '\nInclude conf/extra/certone-ssl.conf\n' >> /usr/local/apache2/conf/httpd.conf
COPY site.conf /usr/local/apache2/conf/extra/certone-ssl.conf
STOPSIGNAL SIGTERM
ENV CERTONE_NODE_ID="node-REPLACE"
ENV CERTONE_TOKEN="REPLACE_WITH_NODE_TOKEN"
ENV CERTONE_DEPLOY_TYPE=httpd
ENTRYPOINT ["/usr/local/bin/certone","exec","--env","--"]
CMD ["httpd-foreground"]

site.conf:

Listen 443
<VirtualHost *:443>
ServerName example.com
DocumentRoot "/usr/local/apache2/htdocs"
SSLEngine on
SSLCertificateFile "/root/.certone/certificates/cert-REPLACE/fullchain.pem"
SSLCertificateKeyFile "/root/.certone/certificates/cert-REPLACE/key.pem"
</VirtualHost>

OpenResty​

Dockerfile:

FROM alpine:3.23 AS certone-download
RUN apk add --no-cache curl ca-certificates
RUN curl -fsSL https://certone.io/downloads/certone/install.sh -o /tmp/install.sh \
&& CERTONE_INSTALL_DIR=/out sh /tmp/install.sh

FROM openresty/openresty:alpine
COPY --from=certone-download /out/certone /usr/local/bin/certone
COPY site.conf /etc/nginx/conf.d/default.conf
STOPSIGNAL SIGTERM
ENV CERTONE_NODE_ID="node-REPLACE"
ENV CERTONE_TOKEN="REPLACE_WITH_NODE_TOKEN"
ENV CERTONE_DEPLOY_TYPE=openresty
ENTRYPOINT ["/usr/local/bin/certone","exec","--env","--"]
CMD ["/usr/local/openresty/bin/openresty","-g","daemon off;"]

Use the nginx site.conf from step 3. These examples assume the standard images' binary paths and startup commands. If a custom image changes them, follow Custom Images and override the commands explicitly.

Runtime user and directories​

The ~ in ~/.certone is the container runtime user's home directory. For example, HOME=/home/app gives a default directory of /home/app/.certone. Adjust the mount point and application certificate paths accordingly, and grant that user the required read/write permissions.

Custom images must set a usable HOME for the runtime user. If no home directory is available, explicitly set absolute CERTONE_STATE_DIR and CERTONE_CERT_DIR paths. You can also override the output location to match an application's existing certificate directory; arrange persistence for that location separately.

Environment-variable mode does not generate config.yaml, and Docker manages the logs. A single template can synchronize multiple certificates. Use a configuration file for multiple application targets or different deployment rules; do not mix the two configuration modes.

Operational notes​

  • Mount the directory containing the certificates, not individual output files.
  • After changing Dockerfile ENV values or updating CertOne, rebuild the image and recreate the container, retaining its data volume.
  • Do not run another sync --once process against a state directory already used by the running agent.
  • A complete, valid cache can support startup during a temporary outage. Continue monitoring certificate expiry and connection failures.
  • Plan how to stop and replace an existing container before reusing its name or production ports.