{"id":406054,"date":"2022-02-15T23:55:51","date_gmt":"2022-02-15T20:55:51","guid":{"rendered":"https:\/\/en.buradabiliyorum.com\/3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it\/"},"modified":"2022-02-15T23:55:51","modified_gmt":"2022-02-15T20:55:51","slug":"3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it","status":"publish","type":"post","link":"https:\/\/buradabiliyorum.com\/en\/3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it\/","title":{"rendered":"#3 Strategies for Automated Production Deployments With Docker \u2013 CloudSavvy IT"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_85 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-6a41c25916a3a\" 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-6a41c25916a3a\" 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-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/buradabiliyorum.com\/en\/3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it\/#1_Docker_Compose_Over_SSH\" >1. Docker Compose Over SSH<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/buradabiliyorum.com\/en\/3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it\/#2_Using_a_Platform-as-a-Service_PaaS\" >2. Using a Platform-as-a-Service (PaaS)<\/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\/3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it\/#3_Orchestration_With_KubernetesDocker_Swarm\" >3. Orchestration With Kubernetes\/Docker Swarm<\/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\/3-strategies-for-automated-production-deployments-with-docker-cloudsavvy-it\/#Summary\" >Summary<\/a><\/li><\/ul><\/nav><\/div>\n<p><strong>&#8220;#3 Strategies for Automated Production Deployments With Docker \u2013 CloudSavvy IT&#8221;<\/strong><\/p>\n<div id=\"article-content-area\">\n<img loading=\"lazy\" decoding=\"async\" class=\"type:primaryImage aligncenter size-full wp-image-14169\" data-pagespeed-lazy-srcset=\"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/09\/993634a1.png?width=398&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1 400w, https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/09\/993634a1.png?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\/2021\/09\/993634a1.png?width=1198&amp;trim=1,1&amp;bg-color=000&amp;pad=1,1\" alt=\"\" width=\"1200\" height=\"675\" src=\"\/pagespeed_static\/1.JiBnMqyl6S.gif\" onload=\"pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\" onerror=\"this.onerror=null;pagespeed.lazyLoadImages.loadIfVisibleAndMaybeBeacon(this);\"\/><\/p>\n<p>Docker is a popular development tool as it simplifies starting isolated instances of your <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>lication with a reproducible configuration. It can also be used in production where it ensures live deployments are identical to your development environment.<\/p>\n<p>Getting a container into production isn\u2019t always as straightforward as running <code>docker run<\/code> on your local machine. It\u2019s not a great idea to be manually pushing images to a registry, connecting to a remote Docker host, and starting your containers. This relies on human intervention so it\u2019s time consuming and error prone.<\/p>\n<p>In this guide, we\u2019ll look at three different strategies you can use that make it easy to automate Docker deployments and maintain consistent configuration. These approaches can be scripted as part of a CI pipeline to start new containers each time your code changes. You\u2019ll need to build your Docker images and push them to a registry as the first stage in your script, then use one of the techniques below to pull the image and start containers in your production environment.<\/p>\n<h2 id=\"docker-compose-over-ssh\"><span class=\"ez-toc-section\" id=\"1_Docker_Compose_Over_SSH\"><\/span>1. Docker Compose Over SSH<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Docker Compose lets you start multiple containers with a single command. Moreover, Compose is configured via a YAML file which helps you version changes and guarantee reproducible deployments.<\/p>\n<p>You may have already used Compose as a local development tool. You need to create a <code>docker-compose.yml<\/code> file in your working directory, then add one or more <code>services<\/code> that define the containers to start:<\/p>\n<pre class=\"yaml\"><code>version: 3&#13;\nservices:&#13;\n  app:&#13;\n    image: example.com\/app:latest&#13;\n    ports:&#13;\n      - 80:80&#13;\n  database:&#13;\n    image: mysql:8.0&#13;\n    expose:&#13;\n      - 3306<\/code><\/pre>\n<p>Once you\u2019ve got a Compose file, use the <code>docker-compose up -d<\/code> command to launch your containers. If you modify the file, repeat the command to apply your changes. Compose will update or replace containers to achieve the new declared state.<\/p>\n<p>Adding the <code>--pull<\/code> flag instructs Compose to try and pull updated images before starting containers. You can also use <code>--force-recreate<\/code> to force the creation of new containers, even if their underlying configuration hasn\u2019t changed.<\/p>\n<p>How does all this relate to production deployments? It means you can use Compose as part of your CI pipeline to effortlessly start containers that satisfy the state you declare in your <code>docker-compose.yml<\/code> file. Running <code>docker-compose up -d --pull<\/code> in each pipeline will give you a set of containers that each run the latest version of their image.<\/p>\n<p>\u00a0<\/p>\n<p>There are several ways you can implement this method. The simplest and safest route is to install Docker and Compose on your production host, then connect to it over SSH. You\u2019d need to use your CI provider\u2019s settings to store SSH credentials as variables accessible to your pipeline. You\u2019d then configure the SSH client in your pipeline, copy the <code>docker-compose.yml<\/code> file to your remote host, and run the\u00a0 <code>docker-compose up<\/code> command.<\/p>\n<p>Here\u2019s a sample script:<\/p>\n<pre><code>mkdir -p ~\/.ssh &amp;&amp; chmod 700 ~\/.ssh&#13;\necho $SSH_PRIVATE_KEY | ssh-add -&#13;\necho $SSH_HOST_KEY &gt; ~\/.ssh\/known_hosts&#13;\nscp docker-compose.yml:ci-user@example.com:\/home\/ci-user\/docker-compose.yml&#13;\nssh -t ci-user@example.com docker-compose up -d<\/code><\/pre>\n<p>Alternatively you could use Docker contexts to run the Compose binary locally, within your pipeline\u2019s environment. This would require you to expose the Docker socket on your remote host; as this can be a security risk, the approach is <a href=\"https:\/\/buradabiliyorum.com\/en\/category\/general\/\" data-internallinksmanager029f6b8e52c=\"3\" title=\"General\" target=\"_blank\" rel=\"noopener\">general<\/a>ly less favorable in situations where SSH could also be used.<\/p>\n<p>Following this method would have you install Docker and Compose on the host that runs your pipelines. Within your pipeline script, you\u2019d register and select a Docker context that points to your remote production host. The connection details would need to be supplied as variables set in your CI provider\u2019s settings panel. With the context selected, you\u2019d run <code>docker-compose up -d<\/code> in your pipeline\u2019s environment but see the command executed against the remote server.<\/p>\n<h2 id=\"using-a-platform-as-a-service-paas\"><span class=\"ez-toc-section\" id=\"2_Using_a_Platform-as-a-Service_PaaS\"><\/span>2. Using a Platform-as-a-Service (PaaS)<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Adopting a Platform-as-a-Service (PaaS) offering is another approach to running Docker containers in production. You can self-host your own with solutions like Dokku or choose a hosted offering such as Amazon ECS, DigitalOcean App Platform, or Heroku.<\/p>\n<p>A PaaS abstracts away the complexity of building images, maintaining detailed configurations, and provisioning your own Docker hosts. You either use Git to directly push your repository to the platform or run a CLI command to upload your changes. The PaaS handles container creation from your source assets, Dockerfiles, or platform-specific config file.<\/p>\n<p>PaaS solutions are a great way to get online quickly with minimal hands-on Docker interaction. They\u2019re easy to integrate into your CI pipeline and most major providers offer sample scripts to get you started. However, it is possible to outgrow a PaaS which could mean you need to rethink your infrastructure in the future.<\/p>\n<p>The steps to automate deployment to your chosen platform will vary by provider. If you\u2019re using Dokku or a similar PaaS with Git integration, your CI script could be as simple as two lines:<\/p>\n<pre><code>git remote add dokku dokku@example.com:app-name&#13;\ngit push dokku master<\/code><\/pre>\n<p>The script adds your Dokku server as a Git remote and pushes up the repository\u2019s content. Dokku will automatically build an image from your <code>Dockerfile<\/code> and start container instances. You\u2019d need to add your CI server\u2019s SSH public key <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/dokku.com\/docs\/deployment\/user-management\">to Dokku for<\/a> this to work; otherwise, your CI script would be unable to authenticate to the platform.<\/p>\n<h2 id=\"orchestration-with-kubernetesdocker-swarm\"><span class=\"ez-toc-section\" id=\"3_Orchestration_With_KubernetesDocker_Swarm\"><\/span>3. Orchestration With Kubernetes\/Docker Swarm<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Using an orchestrator such as Kubernetes or Docker Swarm is arguably the most common way of running live container instances. These tools are purpose-built to deploy and scale containers in production environments.<\/p>\n<p>Orchestrators remove the complexities of infrastructure management, letting you focus on your application and its components. Similarly to Docker Compose, they take a declarative approach to state configuration where you define what the end state should look like. The orchestrator determines the correct sequence of actions to achieve that state.<\/p>\n<p>Kubernetes is the most popular orchestrator. One way to interact with Kubernetes clusters is with Kubectl, the official CLI management tool. Kubectl lets you apply manifest files in YAML format that define the container resources to create in your cluster.<\/p>\n<p>Here\u2019s a simple manifest that creates a single container instance:<\/p>\n<pre class=\"yaml\"><code>apiVersion: apps\/v1&#13;\nkind: Deployment&#13;\nmetadata:&#13;\n  name: demo&#13;\nspec:&#13;\n  replicas: 1&#13;\n  selector:&#13;\n    matchLabels:&#13;\n      app: demo&#13;\n  template:&#13;\n    metadata:&#13;\n      labels:&#13;\n        app: demo&#13;\n    spec:&#13;\n      containers:&#13;\n        - name: demo&#13;\n          image: example.com\/image:latest<\/code><\/pre>\n<p>You can use Kubectl to apply this manifest to a cluster:<\/p>\n<pre><code>kubectl apply -f manifest.yaml<\/code><\/pre>\n<p>Subsequent changes to the file are applied by repeating the command. Kubernetes automatically takes the necessary actions to achieve the new declared state.<\/p>\n<p>This makes Kubernetes a great option for automated production deployments. You can use <code>kubectl apply<\/code> within your pipelines to take the manifests in your repository and apply the declared state to your cluster. Creating a new image tag for each commit would see Kubernetes pull that image and start new containers for the deployment.<\/p>\n<p>To set this up, you\u2019d need to supply the contents of a Kubeconfig config file as a pipeline variable. This gives Kubectl the credentials to use for your cluster connection. The local Kubectl binary would then operate against your remote cluster.<\/p>\n<p>Docker Swarm is another orchestration option which comes integrated with Docker. You can <a rel=\"nofollow noopener\" target=\"_blank\" href=\"https:\/\/docs.docker.com\/compose\/compose-file\/compose-file-v3\/#deploy\">set up a Swarm stack<\/a> using the same <code>docker-compose.yml<\/code> file as described earlier. Similar deployment approaches could then be used, either connecting to the Swarm host over SSH or using a Docker context to modify the target of local Docker binaries.<\/p>\n<p>Orchestrators are much more complex than using plain Compose or a managed PaaS. In the case of Kubernetes, you need to learn new abstractions, terminology, and config file formats before you can deploy your containers. However, clusters also give you extra capabilities which make it easier to maintain applications over the long-term. You can easily scale replicas over multiple hosts, build in redundancy, and aggregate logs and metrics.<\/p>\n<p>Orchestration is therefore the best option for larger systems running multiple containers. That doesn\u2019t mean the industry attention that the tools are receiving should cause you to use Kubernetes for every deployment. Compose or a PaaS will be easier to set up, reason about, and maintain for smaller use cases where you\u2019re less concerned about scalability and vendor lock-in.<\/p>\n<h2 id=\"summary\"><span class=\"ez-toc-section\" id=\"Summary\"><\/span>Summary<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>We\u2019ve looked at three different ways of running containers as production workloads. The implementation details will vary depending on your chosen strategy, supporting toolchain, and CI environment, so we\u2019ve omitted precise description of how you can set up automation as part of your workflow. However, all three can be easily integrated into a CI pipeline that runs each time you merge or push your code.<\/p>\n<p>Orchestration using a tool like Kubernetes has rapidly become the preferred method for scalable deployments of systems running multiple containers. While it can vastly simplify the operation of the services it\u2019s designed for, it also brings a significant learning curve and maintenance overhead so you shouldn\u2019t jump in without considering alternatives.<\/p>\n<p>Smaller systems formed from a few components may see better results from using Compose to start containers with a reproducible config on an existing Docker host. This gives some of the benefits of Kubernetes, such as declarative configuration, without the extra complexity. You may \u201cease in\u201d to orchestration later by adding Docker Swarm support to your existing Compose file, letting you start multiple distributed replicas of containers.<\/p>\n<p>Finally, Platform-as-a-Service options accelerate application deployment without making you think about granular container details. These services offer the prospect of full infrastructure automation from minimal configuration. They can be restrictive in the long-term though so think about how your solution will grow over time before committing yourself.<\/p>\n<p>When deploying any containers into production, you\u2019ll also need to consider image hosting and config injection. You can use a public registry service to make your images available in your production environment. Alternatively, you could run your own private registry and supply credentials as part of your CI pipeline. Config values are usually provided as environment variables which you can define in your CI provider\u2019s settings screen.\n<\/p><\/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\/15340\/3-strategies-for-automated-production-deployments-with-docker\/\" target=\"_blank\" rel=\"noopener\">Source<\/a><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;#3 Strategies for Automated Production Deployments With Docker \u2013 CloudSavvy IT&#8221; Docker is a popular development tool as it simplifies starting isolated instances of your application with a reproducible configuration. It can also be used in production where it ensures live deployments are identical to your development environment. Getting a container into production isn\u2019t always&#8230;<\/p>\n","protected":false},"author":1,"featured_media":406055,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"fifu_image_url":"https:\/\/www.cloudsavvyit.com\/p\/uploads\/2021\/09\/993634a1.png","fifu_image_alt":"","footnotes":""},"categories":[18],"tags":[],"class_list":["post-406054","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\/406054","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=406054"}],"version-history":[{"count":0,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/posts\/406054\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media\/406055"}],"wp:attachment":[{"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/media?parent=406054"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/categories?post=406054"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/buradabiliyorum.com\/en\/wp-json\/wp\/v2\/tags?post=406054"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}