{"id":414820,"date":"2022-03-11T13:00:55","date_gmt":"2022-03-11T10:00:55","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/"},"modified":"2022-03-11T13:00:55","modified_gmt":"2022-03-11T10:00:55","slug":"how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/","title":{"rendered":"#How to Deploy a Caddy Web Server With Docker \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_84 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6a26bbacefca4\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #dd3333;color:#dd3333\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #dd3333;color:#dd3333\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6a26bbacefca4\" checked aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#%E2%80%9CHow_to_Deploy_a_Caddy_Web_Server_With_Docker_%E2%80%93_CloudSavvy_IT%E2%80%9D\" >&#8220;How to Deploy a Caddy Web Server With Docker \u2013 CloudSavvy IT&#8221;<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#Selecting_an_Image_Tag\" >Selecting an Image Tag<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#Starting_a_Basic_Server\" >Starting a Basic Server<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#Setting_Up_HTTPS\" >Setting Up HTTPS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#Adding_Your_Own_Caddyfile\" >Adding Your Own Caddyfile<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#Creating_Docker_Images_For_Your_Sites\" >Creating Docker Images For Your Sites<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/buradabiliyorum.com\/en\/how-to-deploy-a-caddy-web-server-with-docker-cloudsavvy-it\/#Summary\" >Summary<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"%E2%80%9CHow_to_Deploy_a_Caddy_Web_Server_With_Docker_%E2%80%93_CloudSavvy_IT%E2%80%9D\"><\/span>&#8220;How to Deploy a Caddy Web Server With Docker \u2013 CloudSavvy IT&#8221;<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage aligncenter size-full wp-image-15518\" data-pagespeed-lazy-srcset=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/7be949e2.jpeg?width=398&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 400w, https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/7be949e2.jpeg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 1200w\" sizes=\"auto, 400w, 1200w\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/7be949e2.jpeg?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"Graphic showing the logo of the Caddy web server project\" width=\"1202\" height=\"677\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p><a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/caddyserver.com\">Caddy<\/a> is a popular modern web server engineered for high performance and memory safety. It\u2019s written in Go, runs with no dependencies, features built-in support for static site rendering with Markdown, and offers automatic HTTPS.<\/p>\n<p>Caddy\u2019s focused on providing a simple server management experience that gives you useful functionality by default. It can be easier to configure and maintain than rival systems such as Apache and NGINX. In this article, we\u2019ll show how to get your own server running with minimal set up by using Docker with the <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/hub.docker.com\/_\/caddy\">official Caddy image<\/a>.<\/p>\n<h2 id=\"selecting-an-image-tag\"><span class=\"ez-toc-section\" id=\"Selecting_an_Image_Tag\"><\/span>Selecting an Image Tag<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The Caddy image comes in a few different flavors. The latest version of Caddy is shared by all which is v2.4 at the time of writing. You can use <code>2.4.x<\/code> (replacing <code>x<\/code> with a specific patch version), <code>2.4<\/code>, or <code>2<\/code> to pin to the major, minor, or patch component.<\/p>\n<p>Caddy works with Linux and Windows Docker hosts. Alpine Linux, Windows Server Core 1809, and the Windows Server Core 2016 LTSC release are the current operating system options. Referencing a bare Caddy tag such as <code>caddy:2<\/code> will select the <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/download-scripts-themes-apps\/\" data-internallinksmanager029f6b8e52c=\"9\" title=\"Download Scripts &amp; Themes &amp; Apps\" target=\"_blank\" rel=\"noopener\">app<\/a>ropriate image for your platform; you can use variations like <code>2.4-alpine<\/code> or <code>2.4.6-windowsservercore-1809<\/code> instead to be more explicit.<\/p>\n<h2 id=\"starting-a-basic-server\"><span class=\"ez-toc-section\" id=\"Starting_a_Basic_Server\"><\/span>Starting a Basic Server<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Caddy ships in a ready-to-run configuration. The Docker image will serve your web content from the <code>\/usr\/share\/caddy<\/code> directory. You can add your files to the container by mounting a host directory to this path.<\/p>\n<p>Caddy also has separate config and data directories which you should mount Docker volumes to. The <code>\/config<\/code> directory is optional but recommended; it stores your config files but as these are converted <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/caddyserver.com\/docs\">to API requests<\/a>, they don\u2019t strictly need to be persisted. The <code>\/data<\/code> location is vital as it holds Caddy-generated TLS certificates, private keys, and the final server config that\u2019s been processed by the API.<\/p>\n<pre>docker run -d -p 80:80 \\&#13;\n    -v .\/my-website:\/usr\/share\/caddy\/ \\&#13;\n    -v caddy-config:\/config&#13;\n    -v caddy_data:\/data&#13;\n    caddy:2<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15520\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/671de48f.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1048\" height=\"318\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>As an HTTP server, Caddy listens on port 80 by default. This is bound to port 80 on your host via the <code>-p<\/code> flag in the example above.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-15519\" data-pagespeed-lazy-src=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/7b8d7964.png?trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1280\" height=\"790\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Now you can visit <code>http:\/\/localhost<\/code> in your browser to access your site. You should see the <code>index.html<\/code> from your mounted content directory. You\u2019ll get the default Caddy landing page if you didn\u2019t bind anything to <code>\/usr\/share\/caddy<\/code>.<\/p>\n<h2 id=\"setting-up-https\"><span class=\"ez-toc-section\" id=\"Setting_Up_HTTPS\"><\/span>Setting Up HTTPS<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>One of Caddy\u2019s headline features is its automatic TLS support so we\u2019d be remiss not to use it. You need to bind port 443 in addition to port 80 so Caddy can receive HTTPS traffic. The only other change is to supply the domain name your site will be served on. Everything else is handled by Caddy.<\/p>\n<pre>docker run -d -p 80:80 -p 443:443 \\&#13;\n    -v .\/my-website:\/usr\/share\/caddy\/ \\&#13;\n    -v caddy-config:\/config&#13;\n    -v caddy_data:\/data&#13;\n    caddy:2 caddy file-server --domain example.com<\/pre>\n<p>The command after the image name is passed by <code>docker run<\/code> to the Docker image\u2019s entrypoint. In this case, it means <code>caddy file-server ...<\/code> is executed as the container\u2019s foreground process. The <code>--domain<\/code> flag is used to set the domain that Caddy will acquire an HTTPS certificate for. You should check you\u2019ve got an A-type DNS record referencing your Docker host\u2019s IP before you start the container.<\/p>\n<h2 id=\"adding-your-own-caddyfile\"><span class=\"ez-toc-section\" id=\"Adding_Your_Own_Caddyfile\"><\/span>Adding Your Own Caddyfile<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Caddy normally uses a config file <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/caddyserver.com\/docs\/quick-starts\/caddyfile\">called <code>Caddyfile<\/code><\/a> for defining routes and changing server settings. The Docker image loads the Caddyfile at <code>\/etc\/caddy\/Caddyfile<\/code>. Mount your own file to this path to override the default settings that serve <code>\/usr\/share\/caddy<\/code>:<\/p>\n<pre>docker run -d -p 80:80 -p 443:443 \\&#13;\n    -v .\/Caddyfile:\/etc\/caddy\/Caddyfile&#13;\n    -v caddy_data:\/data&#13;\n    caddy:2<\/pre>\n<p>Here\u2019s a simple Caddyfile for a site called <code>example.com<\/code> with HTTPS enabled:<\/p>\n<pre>{&#13;\n    email example@example.com&#13;\n}&#13;\n&#13;\nexample.com {&#13;\n    respond \"It works!\"&#13;\n}<\/pre>\n<p>This minimal config sets the global email address to <code>example@example.com<\/code>. This email will be used when making Let\u2019s Encrypt certificate requests. The <code>example.com<\/code> block provides routing rules for Caddy\u2019s handling of requests to your domain. In this case, the server will always respond with a static message.<\/p>\n<p>More information on the Caddyfile is available in <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/caddyserver.com\/docs\/caddyfile\/concepts\">the Caddy documentation<\/a>. Docker doesn\u2019t change anything here: as long as your file\u2019s available at <code>\/etc\/caddy\/Caddyfile<\/code>, Caddy will load and use it.<\/p>\n<h2 id=\"creating-docker-images-for-your-sites\"><span class=\"ez-toc-section\" id=\"Creating_Docker_Images_For_Your_Sites\"><\/span>Creating Docker Images For Your Sites<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>So far we\u2019ve looked at ad-hoc Caddy usage by starting containers straight from the Caddy base image. In practice it\u2019s more likely you\u2019ll want to create dedicated images for your sites so you don\u2019t have to mount your content each time you start a container.<\/p>\n<p>The Caddy base image is ready to extend with your own instructions for adding content and configuration. Here\u2019s an example Dockerfile which includes a Caddyfile and copies your site\u2019s content to a customized directory:<\/p>\n<pre>FROM caddy:2.4&#13;\nWORKDIR \/my-site&#13;\nCOPY Caddyfile \/etc\/caddy\/Caddyfile&#13;\nCOPY *.html .\/&#13;\nCOPY *.css css\/&#13;\nCOPY *.js js\/<\/pre>\n<p>Now you can build and run your image to start a Caddy server that\u2019s preconfigured for your site:<\/p>\n<pre>docker build -t my-site:latest .&#13;\ndocker run -p 80:80 -p 443:443 -v caddy_data:\/data my-site:latest<\/pre>\n<p>With many sites you\u2019ll want to include extra Caddy modules for additional functionality. The best way to handle these in your Dockerfile is via Caddy\u2019s dedicated <code>builder<\/code> image. This includes tooling needed to put together a custom Caddy instance with specified modules installed.<\/p>\n<p>Docker\u2019s multi-stage builds are ideal for this workflow. Here\u2019s an example that adds Caddy\u2019s <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/caddyserver\/replace-response\"><code>replace-response<\/code><\/a> module so you can rewrite portions of response data using rules in a Caddyfile:<\/p>\n<pre>FROM caddy:2.4-builder AS caddy-build&#13;\nRUN xcaddy build --with github.com\/caddyserver\/replace-response&#13;\n&#13;\nFROM caddy:2.4&#13;\nCOPY --from=caddy-build \/usr\/bin\/caddy \/usr\/bin\/caddy&#13;\nWORKDIR \/my-site&#13;\nCOPY Caddyfile \/etc\/caddy\/Caddyfile&#13;\nCOPY *.html .\/&#13;\nCOPY *.css css\/&#13;\nCOPY *.js js\/<\/pre>\n<p>The first build stage produces a Caddy binary with the <code>replace-response<\/code> module baked in. The <code>xcaddy<\/code> command available in the builder image places its output at <code>\/usr\/bin\/caddy<\/code>.\u00a0 The second stage uses the standard Caddy base image but overwrites the included binary with the custom built one. Your content is then layered in as normal; the result is a Caddy server that incorporates extra modules while retaining full support for the rest of the features in the Docker base image.<\/p>\n<h2 id=\"summary\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Caddy is a modern web server that\u2019s a great choice for efficiently serving static files. It offers a compelling feature set with first-class support for HTTPS, built-in template rendering, and Markdown integration.<\/p>\n<p>Using Docker to host your Caddy server gives you a quick way to deploy an instance without manually downloading binaries or installing service files. It\u2019s a good way to try out Caddy or run it alongside existing workloads in a cluster setting.<\/p>\n<p>As Caddy can act as a reverse proxy and load balancer, you could use it as an entrypoint to route traffic to your other Docker containers. The popular <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/github.com\/lucaslorentz\/caddy-docker-proxy\">Caddy Docker Proxy<\/a> module extends the server\u2019s built-in capabilities with Traefik-like support for automatic route discovery via Docker container labels.<\/p>\n<p>Caddy takes an <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/caddyserver.com\/docs\/quick-starts\/api\">API-first approach<\/a> to configuration which simplifies the management of instances running inside a container. You don\u2019t need to worry too much about injecting config files or managing volumes. As long as the <code>\/data<\/code> directory is persisted, you can make API requests to modify Caddy\u2019s operation without having to use the Docker CLI. This can make it a better choice for containerization when compared to more traditional options like Apache and NGINX.\n<\/div>\n<blockquote><p><strong><span style=\"color: #ff6600;\">If you liked the article, do not forget to share it with your friends. Follow us on\u00a0<span style=\"color: #ff0000;\"><a style=\"color: #ff0000;\" href=\"https:\/\/news.google.com\/publications\/CAAqBwgKMLG0nwswvr63Aw\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Google News<\/a><\/span>\u00a0too, click on the star and choose us from your favorites.<\/span><\/strong><\/p><\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\">For forums sites go to <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/forum.buradabiliyorum.com\/\" target=\"_blank\" rel=\"noopener\">Forum.BuradaBiliyorum.Com<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<blockquote>\n<p style=\"text-align: center;\"><strong>If you want to read more like this article, you can visit our <span style=\"color: #ff9900;\"><a style=\"color: #ff9900;\" href=\"https:\/\/en.buradabiliyorum.com\/technology\/\" target=\"_blank\" rel=\"noopener\">Technology category.<\/a><\/span><\/strong><\/p>\n<\/blockquote>\n<p><span style=\"color: black;\"><a style=\"color: #ff9900;\" href=\"https:\/\/www.cloudsavvyit.com\/15517\/how-to-deploy-a-caddy-web-server-with-docker\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;How to Deploy a Caddy Web Server With Docker \u2013 CloudSavvy IT&#8221; Caddy is a popular modern web server engineered for high performance and memory safety. It\u2019s written in Go, runs with no dependencies, features built-in support for static site rendering with Markdown, and offers automatic HTTPS. Caddy\u2019s focused on providing a simple server management&#8230;<\/p>\n","protected":false},"author":1,"featured_media":414821,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2022\/02\/7be949e2.jpeg","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-414820","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-technology"],"_links":{"self":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/414820","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/comments?post=414820"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/414820\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/414821"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=414820"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=414820"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=414820"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}