<?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>DEV Community: Minaro</title>
    <description>The latest articles on DEV Community by Minaro (@minaro).</description>
    <link>https://dev.to/minaro</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%2F663504%2Ff4588401-1022-4686-b75e-d893f001db56.jpeg</url>
      <title>DEV Community: Minaro</title>
      <link>https://dev.to/minaro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/minaro"/>
    <language>en</language>
    <item>
      <title>Automate React App deployment using GitLab CI/CD, Ansible, Docker</title>
      <dc:creator>Minaro</dc:creator>
      <pubDate>Thu, 06 Jan 2022 18:13:32 +0000</pubDate>
      <link>https://dev.to/minaro/automate-react-app-deployment-using-gitlab-cicd-ansible-docker-43hd</link>
      <guid>https://dev.to/minaro/automate-react-app-deployment-using-gitlab-cicd-ansible-docker-43hd</guid>
      <description>&lt;p&gt;Custom workflow to automate your deployment using Gitlab and Ansible.&lt;/p&gt;

&lt;p&gt;If you want to see your changes online every time you push some code, you need a custom workflow. You are at the right place.&lt;br&gt;
Follow this short tutorial, I have the perfect recipe for you !&lt;/p&gt;

&lt;p&gt;We will use the most suitable tools for our project, let me introduce our little friends :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitLab to host our project and run pipelines&lt;/li&gt;
&lt;li&gt;Ansible to deploy on remote server&lt;/li&gt;
&lt;li&gt;Docker to containerized our app and ship it easily and fast&lt;/li&gt;
&lt;li&gt;ReactJS fontend frameworks for the demo (it could be anything else, but you’ll need to adapt the container)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  1. Create a new project with create-react-app and host it on Gitlab
&lt;/h2&gt;

&lt;p&gt;We will create a new react app with CRA:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn create react-app &amp;lt;project_name&amp;gt; &lt;span class="nt"&gt;--template&lt;/span&gt; typescript
&lt;span class="nb"&gt;cd&lt;/span&gt; &amp;lt;project_name&amp;gt;
git remote add origin &amp;lt;gitlab_project_url&amp;gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; “Initial commit”
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Create CI job with GitLab CI
&lt;/h2&gt;

&lt;p&gt;At the root of your project we will create a new file &lt;code&gt;.gitlab-ci.yml&lt;/code&gt; to enable the gitlab CI.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;p&gt;Currently this file contains only one stage dedicated to the build. We basically install only the &lt;code&gt;dependencies&lt;/code&gt; of our project and not the &lt;code&gt;devDependencies&lt;/code&gt;.&lt;br&gt;
Then we build and we cache the build folder for later jobs.&lt;br&gt;
We also cache the &lt;code&gt;node_modules&lt;/code&gt; folder so the next time we don’t need to download all the &lt;code&gt;node_modules&lt;/code&gt; again.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Containerize and release our app with Docker on the GitLab container registry
&lt;/h2&gt;

&lt;p&gt;We have created a production build for our react app but we still need to create a container to ship it.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;We added the release stage which build the container. We use the cache again but for the layers of the image so the less the container change the faster it will be built. We need to login to the project registry thanks to &lt;a href="https://docs.gitlab.com/ee/ci/variables/predefined_variables.html"&gt;predefined variables&lt;/a&gt; and simply push the freshly created container to the registry.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Deploy and update our app in production
&lt;/h2&gt;

&lt;p&gt;Now we have prepared everything for the deployment but our app is stored in a container registry but still not running in production. We will be a bit hand-made here.&lt;/p&gt;

&lt;h3&gt;
  
  
  4.1 Create a SSH key
&lt;/h3&gt;

&lt;p&gt;First thing, we need to be able to connect our deployment server through SSH. So let’s create an SSH key !&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_ansible &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;
ssh-copy-id &lt;span class="nt"&gt;-i&lt;/span&gt; ~/.ssh/id_ansible &amp;lt;user&amp;gt;@&amp;lt;ip&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The last command will add your public key on the server.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ansible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This command reveal your ssh private key, copy it we will use it in the next step. But do not share it with anyone !&lt;/p&gt;
&lt;h3&gt;
  
  
  4.2 Add a SSH Key to GitLab
&lt;/h3&gt;

&lt;p&gt;In order to connect to your server and deploy the container we need to add this private key to the runner.&lt;br&gt;
To upload the key to GitLab, go to &lt;strong&gt;Settings &amp;gt; CI/CD &amp;gt; Variables&lt;/strong&gt; and click on &lt;strong&gt;&lt;em&gt;Add variable&lt;/em&gt;&lt;/strong&gt;. In &lt;strong&gt;&lt;em&gt;key&lt;/em&gt;&lt;/strong&gt; write &lt;code&gt;ANSIBLE_DEPLOY_KEY&lt;/code&gt; and in &lt;strong&gt;&lt;em&gt;Value&lt;/em&gt;&lt;/strong&gt; paste the private key. If you have not created protected branches or tags, uncheck &lt;strong&gt;&lt;em&gt;Protect variable&lt;/em&gt;&lt;/strong&gt;, click &lt;strong&gt;&lt;em&gt;Add Variable&lt;/em&gt;&lt;/strong&gt; and you're done.&lt;/p&gt;
&lt;h3&gt;
  
  
  4.3 Create a docker-compose file
&lt;/h3&gt;

&lt;p&gt;On your server under &lt;code&gt;/home/&amp;lt;user&amp;gt;/prod&lt;/code&gt; create a &lt;code&gt;docker-compose.yml&lt;/code&gt; in order to run your container.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



&lt;h3&gt;
  
  
  4.4 Create an Ansible Playbook
&lt;/h3&gt;

&lt;p&gt;We will use Ansible to execute remote command on the server during the pipelines, this setup does not aims to explain Ansible; it’s a simple setup.&lt;br&gt;
At the root of your project you can create the &lt;code&gt;ansible/&lt;/code&gt; directory.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;in &lt;code&gt;ansible/hosts&lt;/code&gt; copy/paste the file under and replace the &lt;code&gt;&amp;lt;user&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;ip&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;in &lt;code&gt;ansible/roles/deployment/tasks/main.yml&lt;/code&gt; copy/paste the content of the second file&lt;/li&gt;
&lt;li&gt;in &lt;code&gt;ansible/playbooks&lt;/code&gt; again copy/paste the third file.&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h3&gt;
  
  
  4.5 Deploying with Ansible playbook
&lt;/h3&gt;

&lt;p&gt;Last step, we added the deploy stage that will connect to the server, pull from the registry and only restart the container we pulled.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;h2&gt;
  
  
  Thoughts
&lt;/h2&gt;

&lt;p&gt;I’m aware that this setup does not cover every use case and does not follow every best practice in terms of security, like importing a ssh private key in GitLab or not handling errors if deployment failed.&lt;br&gt;
But I wanted to keep it simple as a basic setup so you can adapt it to your needs, if you have any advise feel free to write a comment, this is my first try so I will definitely improve it.&lt;/p&gt;

&lt;p&gt;Thank you for reading !&lt;/p&gt;

</description>
      <category>ansible</category>
      <category>docker</category>
      <category>gitlab</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
