<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: FarisZR</title>
    <description>The latest articles on Forem by FarisZR (@fariszr).</description>
    <link>https://forem.com/fariszr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1068213%2F26308eee-f10f-4162-beac-67f3e8ededa2.jpeg</url>
      <title>Forem: FarisZR</title>
      <link>https://forem.com/fariszr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/fariszr"/>
    <language>en</language>
    <item>
      <title>Docker compose Gitops using Github Actions</title>
      <dc:creator>FarisZR</dc:creator>
      <pubDate>Thu, 20 Apr 2023 18:05:32 +0000</pubDate>
      <link>https://forem.com/fariszr/docker-compose-gitops-using-github-actions-13jd</link>
      <guid>https://forem.com/fariszr/docker-compose-gitops-using-github-actions-13jd</guid>
      <description>&lt;p&gt;So you have heard about how good GitOps is, and how much better it is than having to manage your containers by hand. But almost every time GitOps is mentioned, it means using K8S. But what about the rest of us mere mortals who are still using Docker Compose?&lt;/p&gt;

&lt;p&gt;That's why I started working on &lt;a href="https://github.com/FarisZR/docker-compose-gitops-action"&gt;docker-compose-gitops-action&lt;/a&gt;, a GitHub action to do GitOps with Docker compose!, it should cover most edge cases for Docker compose CI deployments, swarm, uploading sidecar files, post-upload shell commands, non-exposed servers like Homelabs and more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Server side setup
&lt;/h2&gt;

&lt;p&gt;The action supports two access modes, SSH and Tailscale SSH.&lt;br&gt;
Tailscale SSH is particularly useful for servers behind NAT or without an exposed SSH demon, allowing you to grant SSH access without manually generating keys or exposing the server.&lt;br&gt;
Both Tailscale SSH and SSH require a user with access to the Docker socket &lt;strong&gt;&lt;a href="https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user"&gt;i.e. without the need for sudo&lt;/a&gt;&lt;/strong&gt;. This user can be different from the main user.&lt;/p&gt;
&lt;h2&gt;
  
  
  Repo Setup
&lt;/h2&gt;

&lt;p&gt;This action can be used in two ways&lt;/p&gt;
&lt;h3&gt;
  
  
  Per-project directories
&lt;/h3&gt;

&lt;p&gt;In this case, each project/service will have its own directory with sidecar files and docker-compose.yml.&lt;/p&gt;

&lt;p&gt;This gives you more flexibility in configuring actions for deploying specific directories, so I think this is the way to go. And if there's a small update, you don't have to redeploy the whole repo.&lt;/p&gt;
&lt;h3&gt;
  
  
  Single compose file
&lt;/h3&gt;

&lt;p&gt;If the server is only running a single project, you can put the docker-compose.yml file in the root of the repo and have the action run on every push.&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up the GitHub action
&lt;/h2&gt;

&lt;p&gt;Before we can do anything, we need to set up the GitHub secrets for authentication.&lt;br&gt;
Mainly SSH private key (PEM format) + public key, or an ephemeral Tailscale API key.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;deploy-project&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;project/**'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.github/**'&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name != 'pull_request'&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tailscale&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tailscale/github-action@ce41a99162202a647a4b24c30c558a567b926709&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;authkey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.TAILSCALE_AUTHKEY }}&lt;/span&gt;
          &lt;span class="na"&gt;hostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Github-actions&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aosus/docker-compose-gitops-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Remote Deployment&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;remote_docker_host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root@100.107.201.124&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-p project up -d&lt;/span&gt;
          &lt;span class="na"&gt;tailscale_ssh&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;compose_file_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project/docker-compose.yml&lt;/span&gt;
          &lt;span class="na"&gt;upload_directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
          &lt;span class="c1"&gt;#post_upload_command: touch "upload_command.txt"&lt;/span&gt;
          &lt;span class="na"&gt;docker_compose_directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Whenever the action file is edited or the project folder is changed on the main branch, this action is triggered.&lt;br&gt;
I'm using Tailscale SSH, so I need to have the official Tailscale action as a pre-deploy step, to not have to specify any ssh keys or actually open any ports.&lt;/p&gt;

&lt;p&gt;Just replace &lt;code&gt;tailscale_ssh&lt;/code&gt; with this if you want to use pure ssh:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;        &lt;span class="na"&gt;ssh_public_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_KEY }}&lt;/span&gt;
        &lt;span class="na"&gt;ssh_private_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SSH_PRIVATE_KEY }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be sure to set up these secrets before running the action!&lt;/p&gt;

&lt;p&gt;I also enabled &lt;code&gt;upload_directory&lt;/code&gt; and set &lt;code&gt;docker_compose_directory&lt;/code&gt; as &lt;code&gt;project&lt;/code&gt;.&lt;br&gt;
The &lt;code&gt;project&lt;/code&gt; directory will be uploaded to the server. This is useful if a container needs extra config files, and you don't want to rebuild a custom image with the config files on every image update.&lt;br&gt;
It will also upload the docker-compose file since it is included in the directory.&lt;/p&gt;

&lt;p&gt;If you need to change file permissions after uploading, you can use &lt;code&gt;post_upload_command&lt;/code&gt; to &lt;code&gt;chmod&lt;/code&gt; or &lt;code&gt;chown&lt;/code&gt; files, although in most cases you will need to use sudo.&lt;/p&gt;

&lt;p&gt;That should do the trick, just create an action for each of your projects, and you should have your very own Compose-powered Gitops workflow!&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Photo generated by Lexica AI, and no Lexica, you can't copyright &lt;a href="https://www.theverge.com/2022/2/21/22944335/us-copyright-office-reject-ai-generated-art-recent-entrance-to-paradise"&gt;AI generated images&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>gitops</category>
      <category>github</category>
      <category>githubactions</category>
    </item>
  </channel>
</rss>
