{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreidz3rx2dv2ekg7cv6y7raybubpepxdhwzrplxnthvrfmgpxdnmqle",
"uri": "at://did:plc:25rdn5elo5izoxrmtis34zuk/app.bsky.feed.post/3mousmrikpn52"
},
"coverImage": {
"$type": "blob",
"ref": {
"$link": "bafkreih7yr4zusfoajkamv43hlgn576nhdyskdinjzzpx5jmpu4inupi3u"
},
"mimeType": "image/webp",
"size": 25072
},
"path": "/dev-sandesh/how-to-fix-docker-login-x509-certificate-errors-behind-a-corporate-proxy-8dj",
"publishedAt": "2026-06-22T11:17:43.000Z",
"site": "https://dev.to",
"tags": [
"docker",
"proxy",
"security",
"devops"
],
"textContent": "## **Introduction**\n\nEnterprise and banking environments commonly enforce strict network-security controls. Internet access is often limited to a DMZ, while management zones and internal application environments have no direct internet connectivity.\n\nIn these environments, outbound traffic usually passes through an approved corporate proxy. This approach improves monitoring, access control, compliance, and auditability. However, it can create an unexpected issue when engineers run Docker commands such as `docker login` or `docker pull`.\n\nA common error is:\n\n\n\n Error response from daemon: Get \"https://registry-1.docker.io/v2/\":\n tls: failed to verify certificate: x509: certificate signed by unknown authority\n\n\nThis article explains why the error occurs, why common TLS-bypass approaches are not appropriate for Docker, and how to permanently fix the issue by adding the corporate proxy certificate authority (CA) certificate to both the operating system and Docker’s registry trust store.\n\n## **Why Docker Login Fails in Restricted Banking Environments**\n\nIn a typical banking infrastructure, environments are segmented to reduce risk:\n\n * **DMZ:** Controlled internet access is available through an enterprise proxy.\n\n * **Management Zone (MZ):** Administrative systems are isolated from the public internet.\n\n * **Application and production zones:** Outbound connectivity is heavily restricted or completely blocked.\n\n * **Corporate proxy:** Inspects, controls, logs, and routes approved outbound traffic.\n\n\n\n\nWhen Docker attempts to connect to Docker Hub, it communicates with endpoints such as:\n\n\n\n registry-1.docker.io\n docker.io\n auth.docker.io\n\n\nIf the corporate proxy performs TLS or SSL inspection, it decrypts and re-encrypts HTTPS traffic. The proxy presents a certificate signed by the organization’s internal CA rather than the public CA expected by Docker.\n\nIf Docker does not trust that internal CA, certificate validation fails and Docker returns the `x509: certificate signed by unknown authority` error.\n\n## **Why`curl -k` and `wget --no-check-certificate` Are Not a Docker Solution**\n\nFor basic package downloads, teams may temporarily bypass certificate validation with commands such as:\n\n\n\n curl -k https://example.com\n\n\nor:\n\n\n\n wget --no-check-certificate https://example.com\n\n\nThese commands disable TLS certificate validation. While they may help with short-term troubleshooting, they should not be used as a permanent solution in a regulated environment.\n\nDocker works differently. Docker image operations are performed by the Docker daemon, which validates registry certificates independently. A successful `curl -k` test does not mean Docker will trust the same endpoint.\n\nDisabling TLS validation weakens the security model and creates a risk of man-in-the-middle attacks. The correct approach is to install and trust the corporate proxy CA certificate.\n\n## **Understanding Docker Daemon, Docker CLI, and Proxy Configuration**\n\nA frequent source of confusion is the difference between the Docker CLI and the Docker daemon.\n\n### **Docker CLI**\n\nThe Docker CLI is the command-line tool used by administrators and developers:\n\n\n\n docker login\n docker pull nginx\n docker build .\n docker push my-registry.example.com/app:1.0\n\n\nThe CLI sends commands to the Docker daemon.\n\n### **Docker Daemon**\n\nThe Docker daemon is the background service responsible for actions such as:\n\n * Pulling container images\n\n * Pushing images to registries\n\n * Building images\n\n * Creating and running containers\n\n * Connecting to external registries\n\n\n\n\nBecause the daemon establishes registry connections, proxy configuration and certificate trust must be correctly configured for the daemon.\n\n### **Proxy Configuration Is Not Certificate Trust**\n\nConfiguring a proxy tells Docker where to send outbound traffic. It does not automatically make Docker trust certificates generated by a TLS-inspecting proxy.\n\nFor example, this configuration routes Docker daemon traffic through a proxy:\n\n\n\n [Service]\n Environment=\"HTTP_PROXY=http://example.com\"\n Environment=\"HTTPS_PROXY=http://example.com\"\n Environment=\"NO_PROXY=localhost,127.0.0.1,.somecompany.com\"\n\n\nHowever, if the proxy re-signs HTTPS traffic using an internal CA, Docker still requires that CA certificate to validate the connection.\n\n## **When to Use`insecure-registries`**\n\nDocker supports an `insecure-registries` setting in `/etc/docker/daemon.json`.\n\nExample:\n\n\n\n {\n \"insecure-registries\": [\"my-registry-ip:5000\"]\n }\n\n\nThis setting is useful only for an internal registry that is intentionally running over HTTP or has an untrusted certificate.\n\nIt should not be used for Docker Hub endpoints such as:\n\n\n\n docker.io\n registry-1.docker.io\n\n\nMarking a public registry as insecure disables important security protections. In banking and enterprise environments, the preferred solution is to trust the organization’s proxy CA certificate.\n\n## **Permanent Fix: Add the Corporate Proxy CA Certificate**\n\nThe permanent fix has two parts:\n\n 1. Add the proxy CA certificate to the operating system trust store.\n\n 2. Add the proxy CA certificate to Docker’s registry-specific certificate directory.\n\n\n\n\nThis ensures that both the host operating system and Docker trust the certificate presented by the corporate proxy.\n\n## **Step 1: Export the Proxy Certificate**\n\nUse OpenSSL to retrieve the certificate chain from Docker Hub through the corporate proxy.\n\nReplace the proxy IP address and port with your environment’s proxy details.\n\n\n\n openssl s_client \\\n -proxy <Proxy-server-IP>:<Proxy-port> \\\n -showcerts \\\n -connect registry-1.docker.io:443 \\\n </dev/null 2>/dev/null \\\n | sed -n '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' \\\n > proxy-ca.crt\n\n\nThis command connects to `registry-1.docker.io` through the proxy and saves the presented certificates into a file named `proxy-ca.crt`.\n\n### **Important Validation Step**\n\nBefore trusting the certificate, confirm that it belongs to the approved corporate proxy or corporate certificate authority.\n\n\n\n openssl x509 -in proxy-ca.crt -noout -subject -issuer -dates\n\n\nReview the certificate subject, issuer, and expiration dates. Do not install an unknown or unapproved certificate.\n\n## **Step 2: Add the Certificate to the RHEL Trust Store**\n\nFor RHEL, Rocky Linux, AlmaLinux, CentOS Stream, and similar distributions, copy the CA certificate into the system trust anchor directory.\n\n\n\n sudo cp proxy-ca.crt /etc/pki/ca-trust/source/anchors/corporate-proxy.crt\n\n\nUpdate the operating system certificate trust database:\n\n\n\n sudo update-ca-trust extract\n\n\nThis step allows system tools and services to trust the corporate proxy CA.\n\n## **Step 3: Add the Certificate to Docker’s Registry Trust Store**\n\nDocker supports registry-specific CA certificates under `/etc/docker/certs.d/`.\n\nCreate a directory for the Docker Hub registry endpoint:\n\n\n\n sudo mkdir -p /etc/docker/certs.d/registry-1.docker.io/\n\n\nCopy the corporate proxy CA certificate into the directory using the required filename:\n\n\n\n sudo cp proxy-ca.crt /etc/docker/certs.d/registry-1.docker.io/ca.crt\n\n\nDocker treats `*.crt` files in this directory as trusted CA roots for that registry.\n\n## **Step 4: Configure Docker Daemon Proxy Settings**\n\nIf the Docker host needs the proxy to reach Docker Hub, create a systemd drop-in configuration.\n\n\n\n sudo mkdir -p /etc/systemd/system/docker.service.d/\n\n\nCreate the proxy configuration file:\n\n\n\n sudo vi /etc/systemd/system/docker.service.d/http-proxy.conf\n\n\nAdd the following configuration and replace the example values:\n\n\n\n [Service]\n Environment=\"HTTP_PROXY=http://proxy.example.com:8080\"\n Environment=\"HTTPS_PROXY=http://proxy.example.com:8080\"\n Environment=\"NO_PROXY=localhost,127.0.0.1,.somecompany.com\"\n\n\nThe `NO_PROXY` value should include internal domains, internal registries, loopback addresses, and services that should not use the corporate proxy.\n\n## **Step 5: Reload systemd and Restart Docker**\n\nAfter updating the certificate and proxy configuration, reload systemd and restart the Docker daemon.\n\n\n\n sudo systemctl daemon-reload\n sudo systemctl restart docker\n\n\nVerify that Docker is running:\n\n\n\n sudo systemctl status docker\n\n\n## **Step 6: Test Docker Login and Image Pull**\n\nTest Docker Hub authentication:\n\n\n\n docker login\n\n\nThen test an image pull:\n\n\n\n docker pull hello-world\n\n\nIf the certificate trust and proxy configuration are correct, Docker should connect successfully without the `x509` certificate error.\n\n## **Troubleshooting Checklist**\n\n### **Verify the Docker Daemon Proxy Environment**\n\nRun:\n\n\n\n sudo systemctl show docker --property=Environment\n\n\nConfirm that `HTTP_PROXY`, `HTTPS_PROXY`, and `NO_PROXY` are present and correct.\n\n### **Verify the Docker Certificate File**\n\nConfirm that the registry certificate directory exists:\n\n\n\n sudo ls -l /etc/docker/certs.d/registry-1.docker.io/\n\n\nExpected output should include:\n\n\n\n ca.crt\n\n\n### **Verify the Certificate Format**\n\nDocker expects a PEM-formatted certificate. Validate the file:\n\n\n\n openssl x509 -in /etc/docker/certs.d/registry-1.docker.io/ca.crt -text -noout\n\n\n### **Check Docker Service Logs**\n\nReview Docker daemon logs for detailed certificate or proxy errors:\n\n\n\n sudo journalctl -u docker -n 100 --no-pager\n\n\n### **Confirm Required Docker Hub Endpoints Are Allowed**\n\nDepending on the operation, Docker may need access to multiple endpoints, including:\n\n\n\n registry-1.docker.io\n auth.docker.io\n production.cloudflare.docker.com\n\n\nYour network and proxy teams should allow the required Docker Hub domains according to organizational security policy.\n\n## **Security Best Practices for Banking and Enterprise Environments**\n\n * Use the approved corporate proxy instead of direct internet access.\n\n * Do not permanently disable TLS certificate validation.\n\n * Do not configure public registries as insecure.\n\n * Obtain the proxy root CA certificate from the security or network team whenever possible.\n\n * Validate certificate ownership, issuer, expiration date, and fingerprint before installation.\n\n * Use an internal container registry or approved registry mirror for production workloads.\n\n * Restrict image sources to approved registries.\n\n * Scan container images before promoting them to production.\n\n * Use immutable image tags or image digests for deployment.\n\n * Document proxy, certificate, and registry configurations as infrastructure-as-code where possible.\n\n\n\n\n## **Conclusion**\n\nThe Docker error `x509: certificate signed by unknown authority` is common in restricted enterprise environments where a corporate proxy performs TLS inspection.\n\nThe issue is not solved by configuring only a Docker proxy or by using insecure registry settings for Docker Hub. Proxy configuration controls network routing, while CA certificate installation establishes trust.\n\nThe secure and permanent solution is to install the corporate proxy CA certificate into the host operating system trust store and Docker’s registry-specific certificate directory. Once Docker trusts the proxy CA, `docker login`, `docker pull`, and image builds can work reliably while maintaining the security controls required in banking environments.",
"title": "How to Fix Docker Login x509 Certificate Errors Behind a Corporate Proxy"
}