<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ mongo - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ mongo - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 23 Jun 2026 22:45:24 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/mongo/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ MERN App Development – How to Build a CI/CD Pipeline with Jenkins ]]>
                </title>
                <description>
                    <![CDATA[ By Rakesh Potnuru As you continue to develop your software, you must also continue to integrate it with previous code and deploy it to servers.  Manually doing this is a time-consuming process that can occasionally result in errors. So we need to do ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/automate-mern-app-deployment-with-jenkins/</link>
                <guid isPermaLink="false">66d460c5d14641365a05095d</guid>
                
                    <category>
                        <![CDATA[ continuous deployment ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Continuous Integration ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Express ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Jenkins ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mongo ]]>
                    </category>
                
                    <category>
                        <![CDATA[ node ]]>
                    </category>
                
                    <category>
                        <![CDATA[ React ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 08 Mar 2023 17:42:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/03/CICD-Pipeline-with-Jenkins.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Rakesh Potnuru</p>
<p>As you continue to develop your software, you must also continue to integrate it with previous code and deploy it to servers. </p>
<p>Manually doing this is a time-consuming process that can occasionally result in errors. So we need to do this in a continuous and automated manner – which is what you will learn in this article.</p>
<p>We'll go over how you can improve your MERN (MongoDB, Express, React, and NodeJs) app development process by setting up a CI/CD pipeline with Jenkins. You'll see how to automate deployment for faster, more efficient releases.</p>
<h2 id="heading-lets-get-started">Let's Get Started</h2>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li>Basic understanding of MERN stack technologies.</li>
<li>Basic understanding of Docker.</li>
<li>Get source code from <a target="_blank" href="https://github.com/itsrakeshhq/productivity-app">GitHub</a></li>
</ul>
<h2 id="heading-the-problem">The Problem</h2>
<p>Consider this <a target="_blank" href="https://github.com/itsrakeshhq/productivity-app">productivity app</a> – it's a MERN project that we are going to use in this article. There are numerous steps we must complete, from building the application to pushing it to the Docker hub. </p>
<p>First, we must run tests with a command to determine whether all tests pass or not. If all tests pass, we build the Docker images and then push those images to Docker Hub. If your application is extremely complex, you may need to take additional steps. </p>
<p>Now, imagine that we're doing everything manually, which takes time and can lead to mistakes.</p>
<p><img src="https://i.imgur.com/iWAmMm4.jpg" alt="Waiting for deployment without devops meme" width="1600" height="840" loading="lazy">
<em>Waiting for deployment without devops meme</em></p>
<h2 id="heading-the-solution">The Solution</h2>
<p>To address this problem, we can create a CI/CD <strong>Pipeline</strong>. So, whenever you add a feature or fix a bug, this pipeline gets triggered. This automatically performs all of the steps from testing to deploying.</p>
<h2 id="heading-what-is-cicd-and-why-is-it-important">What is CI/CD and Why is it Important?</h2>
<p><strong>C</strong>ontinuous <strong>I</strong>ntegration and <strong>C</strong>ontinuous <strong>D</strong>eployment is a series of steps performed to automate software integration and deployment. CI/CD is the heart of DevOps.</p>
<p><img src="https://i.imgur.com/uMFtPwJ.png" alt="ci cd steps" width="1920" height="1080" loading="lazy">
<em>CI/CD steps</em></p>
<p>From development to deployment, our MERN app goes through four major stages: testing, building Docker images, pushing to a registry, and deploying to a cloud provider. All of this is done manually by running various commands. And we need to do this every time a new feature is added or a bug is fixed. </p>
<p>But this will significantly reduce developer productivity, which is why CI/CD can be so helpful in automating this process. In this article, we will cover the steps up until pushing to the registry.</p>
<p><img src="https://i.imgur.com/g2omESy.png" alt="ci cd meme" width="1600" height="840" loading="lazy">
<em>CI/CD meme</em></p>
<h2 id="heading-the-project">The Project</h2>
<p>The project we are going to use in this tutorial is a very simple full-stack MERN application.</p>
<p><img src="https://i.imgur.com/GSvRlQ0.gif" alt="project demo" width="600" height="338" loading="lazy">
<em>Project demo</em></p>
<p>It contains two microservices.</p>
<ol>
<li>Frontend</li>
<li>Backend</li>
</ol>
<p>You can learn more about the project <a target="_blank" href="https://blog.itsrakesh.co/lets-build-and-deploy-a-full-stack-mern-web-application">here</a>.</p>
<p>Both of these applications contains a Dockerfile. You can learn how to dockerize a MERN application <a target="_blank" href="https://blog.itsrakesh.co/dockerizing-your-mern-stack-app-a-step-by-step-guide">here</a>.</p>
<h2 id="heading-what-is-jenkins">What is Jenkins?</h2>
<p>To run a CI/CD pipeline, we need a CI/CD server. This is where all of the steps written in a pipeline run. </p>
<p>There are numerous services available on the market, including GitHub Actions, Travis CI, Circle CI, GitLab CI/CD, AWS CodePipeline, Azure DevOps, and Google Cloud Build. Jenkins is one of the popular CI/CD tools, and it's what we'll use here.</p>
<h2 id="heading-how-to-set-up-jenkins-server-on-azure">How to Set Up Jenkins Server on Azure</h2>
<p>Because Jenkins is open source and it doesn't provide a cloud solution, we must either run it locally or self-host on a cloud provider. Now, running locally can be difficult, particularly for Windows users. As a result, I've chosen to self-host it on Azure for this demo.</p>
<p>If you want to run locally or self-host somewhere other than Azure (follow <a target="_blank" href="https://www.jenkins.io/doc/book/installing/">these</a> guides by Jenkins), skip this section and proceed to the <strong>How to Configure Jenkins</strong> section.</p>
<p>First, you'll need to sign in to your <a target="_blank" href="https://Azure.microsoft.com?wt.mc_id=studentamb_90351">Azure</a> account (Create one if you don't have one already). Open Azure Cloud Shell.</p>
<p><img src="https://i.imgur.com/IN6RXAe.png" alt="opening azure cloud shell" width="2120" height="467" loading="lazy">
<em>Opening Azure Cloud Shell</em></p>
<p>Then create a directory called <code>jenkins</code> to store all the Jenkins config, and switch to that directory:</p>
<pre><code class="lang-bash">mkdir jenkins
<span class="hljs-built_in">cd</span> jenkins
</code></pre>
<p>Create a file called <code>cloud-init-jenkins.txt</code>. Open with nano or vim,</p>
<pre><code class="lang-bash">touch cloud-init-jenkins.txt
nano cloud-init-jenkins.txt
</code></pre>
<p>and paste this code into it:</p>
<pre><code class="lang-bash"><span class="hljs-comment">#cloud-config</span>
package_upgrade: <span class="hljs-literal">true</span>
runcmd:
  - sudo apt install openjdk-11-jre -y
  - wget -qO - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -
  - sh -c <span class="hljs-string">'echo deb https://pkg.jenkins.io/debian-stable binary/ &gt; /etc/apt/sources.list.d/jenkins.list'</span>
  - sudo apt-get update &amp;&amp; sudo apt-get install jenkins -y
  - sudo service jenkins restart
</code></pre>
<p>Here, we'll use this file to install Jenkins after creating a virtual machine. First, we install openjdk, which is required for Jenkins to function. The Jenkins service is then restarted after we install it.</p>
<p>Next, create a resource group. (A resource group in Azure is like a container that holds all the related resources of a project in one group. Learn more about resource groups <a target="_blank" href="https://learn.microsoft.com/en-us/azure/azure-resource-manager/management/manage-resource-groups-portal#what-is-a-resource-group?wt.mc_id=studentamb_90351">here</a>.)</p>
<pre><code class="lang-bash">az group create --name jenkins-rg --location centralindia
</code></pre>
<p><strong>Note:</strong> make sure to change the location to the one closest to you.</p>
<p>Now, create a virtual machine.</p>
<pre><code class="lang-bash">az vm create \
--resource-group jenkins-rg \
--name jenkins-vm \
--image UbuntuLTS \
--admin-username <span class="hljs-string">"azureuser"</span> \
--generate-ssh-keys \
--public-ip-sku Standard \
--custom-data cloud-init-jenkins.txt
</code></pre>
<p>You can verify the VM installation with this command:</p>
<pre><code class="lang-bash">az vm list -d -o table --query <span class="hljs-string">"[?name=='jenkins-vm']"</span>
</code></pre>
<p>Don't be confused. This command simply displays JSON data in a tabular format for easy verification.</p>
<p>Jenkins server runs on port <code>8080</code>, so we need to expose this port on our VM. You can do that like this:</p>
<pre><code class="lang-bash">az vm open-port \
--resource-group jenkins-rg \
--name jenkins-vm  \
--port 8080 --priority 1010
</code></pre>
<p>Now we can access the Jenkins dashboard in the browser with the URL <code>http://&lt;your-vm-ip&gt;:8080</code>. Use this command to get the VM IP address:</p>
<pre><code class="lang-bash">az vm show \
--resource-group jenkins-rg \
--name jenkins-vm -d \
--query [publicIps] \
--output tsv
</code></pre>
<p>You can now see the Jenkins application in your browser.</p>
<p><img src="https://i.imgur.com/Sy1Glar.png" alt="jenkins dashboard" width="2007" height="1025" loading="lazy">
<em>Jenkins dashboard</em></p>
<p>As you'll notice, Jenkins is asking us to provide an admin password which is automatically generated during its installation.</p>
<p>But first let's SSH into our virtual machine where Jenkins is installed.</p>
<pre><code class="lang-bash">ssh azureuser@&lt;ip_address&gt;
</code></pre>
<p>Now, type in the below command to get the password:</p>
<pre><code class="lang-bash">sudo cat /var/lib/jenkins/secrets/initialAdminPassword
</code></pre>
<p>Copy and paste it. Then click <strong>Continue</strong>.</p>
<h2 id="heading-how-to-configure-jenkins">How to Configure Jenkins</h2>
<p>First, you'll need to click <strong>Install suggested plugins</strong>. It will take some time to install all the plugins.</p>
<p><img src="https://i.imgur.com/vDaaqE3.png" alt="installing suggested plugins" width="2010" height="1095" loading="lazy">
<em>Installing suggested plugins</em></p>
<p>An admin user is needed to restrict access to Jenkins. So go ahead and create one. After finishing, click <strong>Save and continue</strong>.</p>
<p><img src="https://i.imgur.com/qqkwQN6.png" alt="create an admin user" width="2010" height="1036" loading="lazy">
<em>Create an admin user</em></p>
<p>Now you will be presented with the Jenkins dashboard.</p>
<p>The first step is to install the "Blue Ocean" plugin. Jenkins has a very old interface, which may make it difficult for some people to use. This blue ocean plugin provides a modern interface for some Jenkins components (like creating a pipeline).</p>
<p>To install plugins, go to <strong>Manage Jenkins</strong> -&gt; click <strong>Manage Plugins</strong> under "System Configuration" -&gt; <strong>Available plugins</strong>. Search for "Blue Ocean" -&gt; check the box and click <strong>Download now and install after restart</strong>.</p>
<p><img src="https://i.imgur.com/dAKBLiq.png" alt="blue ocean" width="1920" height="1080" loading="lazy">
<em>Blue ocean</em></p>
<p>Great, we're all set. Now let's create a pipeline.</p>
<h2 id="heading-how-to-write-a-jenkinsfile">How to Write a Jenkinsfile</h2>
<p>To create a pipeline, we need a <strong>Jenkinsfile</strong>. This file contains all the pipeline configurations – stages, steps, and so on. Jenkinsfile is to Jenkins as a Dockerfile is to Docker.</p>
<p>Jenkinsfile uses the <strong>Groovy</strong> syntax. The syntax is very simple. You can understand everything by just looking at it.</p>
<p>Let's start by writing:</p>
<pre><code class="lang-groovy">pipeline {

}
</code></pre>
<p>The word 'agent' should be the first thing you mention in the pipeline. An agent is similar to a container or environment in which jobs run. You can use multiple agents to run jobs in parallel. You can find more information about Jenkins agents can <a target="_blank" href="https://www.jenkins.io/doc/book/using/using-agents/">here</a>.</p>
<pre><code class="lang-groovy">pipeline {
    agent any
}
</code></pre>
<p>Here we are telling Jenkins to use any available agent.</p>
<p>We have a total of 5 stages in our pipeline:</p>
<p><img src="https://i.imgur.com/ezvdElo.png" alt="ci cd pipeline stages" width="1920" height="1080" loading="lazy">
<em>CI/CD pipeline stages</em></p>
<h3 id="heading-stage-1-checkout-code">Stage 1: Checkout code</h3>
<p>Different CI/CD tools use different naming conventions. In Jenkins, these are referred to as stages. In each stage we write various steps.</p>
<p>Our first stage is checking out code from a source code management system (in our case, GitHub).</p>
<pre><code class="lang-groovy">pipeline {
    agent any

    stages {
        stage('Checkout') {
            steps {
                checkout scm
            }
        }
    }
}
</code></pre>
<p>Commit the changes and push to your GitHub repo.</p>
<p>Since we haven't created any pipelines yet, let's do that now.</p>
<p>Before we begin, we must ensure that Git is installed on our system. If you followed my previous steps to install Jenkins on an Azure VM, Git is already installed. </p>
<p>You can test it by running the following command (make you are still SSHed into the VM):</p>
<pre><code class="lang-bash">git --version
</code></pre>
<p>If it isn't already installed, you can do so with:</p>
<pre><code class="lang-bash">sudo apt install git
</code></pre>
<p>Open blue ocean. Click <strong>Create new pipeline</strong>.</p>
<p><img src="https://i.imgur.com/FNffT6p.png" alt="creating new pipeline" width="2010" height="1036" loading="lazy">
<em>Creating new pipeline</em></p>
<p>Then select your source code management system. If you chose GitHub, you must provide an access token for Jenkins to access your repository. I recommend clicking on <strong>Create an access token here</strong> because it is a template with all of the necessary permissions. Then click <strong>Connect</strong>.</p>
<p><img src="https://i.imgur.com/H9TUsHV.png" alt="selecting scm" width="2010" height="1036" loading="lazy">
<em>Selecting scm</em></p>
<p>After that, a pipeline will be created. Since our repository already contains a Jenkinsfile, Jenkins automatically detects it and runs the stages and steps we mentioned in the pipeline.</p>
<p>If everything went well, the entire page will turn green. (Other colors: <strong>blue</strong> indicates that the pipeline is running, <strong>red</strong> indicates that something went wrong in the pipeline, and <strong>gray</strong> indicates that we stopped the pipeline.)</p>
<p><img src="https://i.imgur.com/FtvJlND.png" alt="stage one successful" width="1884" height="486" loading="lazy">
<em>Stage one successful</em></p>
<h3 id="heading-stage-2-run-frontend-tests">Stage 2: Run frontend tests</h3>
<p>In general, all the CI/CD pipelines contains some tests that needs to be run before deploying. So I added simple tests to both the frontend and backend. Let's start with the frontend tests.</p>
<pre><code class="lang-groovy">stage('Client Tests') {
    steps {
        dir('client') {
            sh 'npm install'
            sh 'npm test'
        }
    }
}
</code></pre>
<p>We're changing the directory to <code>client/</code> because that's where the frontend code is. And then install the dependencies with <code>npm install</code> and run the tests with <code>npm test</code> in a shell.</p>
<p>Again, before we restart the pipeline, we have to make sure node and npm are installed or not. Install node and npm with these commands in the virtual machine:</p>
<pre><code class="lang-bash">curl -sL https://deb.nodesource.com/setup_16.x | sudo -E bash -
</code></pre>
<p>After that, run the following:</p>
<pre><code class="lang-bash">sudo apt-get install -y nodejs
</code></pre>
<p>Now, commit the code and restart the pipeline.</p>
<p><img src="https://i.imgur.com/OWYcdDu.png" alt="run client tests" width="1886" height="438" loading="lazy">
<em>Run client tests</em></p>
<h3 id="heading-stage-3-run-backend-tests">Stage 3: Run backend tests</h3>
<p>Now do the same thing for the backend tests.</p>
<p>But there is one thing we need to do before we proceed. If you take a look at the codebase and <code>activity.test.js</code>, we are using a few environment variables. So let's add these environment varibales in Jenkins.</p>
<h4 id="heading-how-to-add-environment-variables-in-jenkins">How to add environment variables in Jenkins</h4>
<p>To add environment variables, go to <strong>Manage Jenkins</strong> -&gt; click <strong>Manage Credentials</strong> under "Security" -&gt;  <strong>System</strong> -&gt; <strong>Global credentials (unrestricted)</strong> -&gt; click <strong>+ Add Credentials</strong>.</p>
<p>For <strong>Kind</strong> select "Secret text", leave <strong>Scope</strong> default, and for <strong>Secret</strong> write the secret value and <strong>ID</strong>. This is what we use when using these environment variables in the Jenkinsfile.</p>
<p>Add the following env variables:</p>
<p><img src="https://i.imgur.com/xGjg2mG.png" alt="environment variables" width="2091" height="796" loading="lazy">
<em>Environment variables</em></p>
<p>Then in the Jenkinsfile, use these env variables:</p>
<pre><code class="lang-groovy">environment {
    MONGODB_URI = credentials('mongodb-uri')
    TOKEN_KEY = credentials('token-key')
    EMAIL = credentials('email')
    PASSWORD = credentials('password')
}
</code></pre>
<p>Add a stage to install dependencies, set these variables in the Jenkins environment, and run the tests:</p>
<pre><code class="lang-groovy">stage('Server Tests') {
    steps {
        dir('server') {
            sh 'npm install'
            sh 'export MONGODB_URI=$MONGODB_URI'
            sh 'export TOKEN_KEY=$TOKEN_KEY'
            sh 'export EMAIL=$EMAIL'
            sh 'export PASSWORD=$PASSWORD'
            sh 'npm test'
        }
    }
}
</code></pre>
<p>Again, commit the code and restart the pipeline.</p>
<p><img src="https://i.imgur.com/hpjMUyT.png" alt="run server tests" width="1059" height="595" loading="lazy">
<em>Run server tests</em></p>
<h3 id="heading-stage-4-build-docker-images">Stage 4: Build Docker images</h3>
<p>Now, we have to specify a step to build the Docker images from the Dockerfiles.</p>
<p>Before we proceed, install Docker in the VM (if you don't already have it installed).</p>
<p>To install Docker:</p>
<pre><code class="lang-bash">sudo apt install docker.io
</code></pre>
<p>Add the user <code>jenkins</code> to the <code>docker</code> group so that Jenkins can access the Docker daemon – otherwise you'll get a permission denied error.</p>
<pre><code class="lang-bash">sudo usermod -a -G docker jenkins
</code></pre>
<p>Then restart the <code>jenkins</code> service.</p>
<pre><code class="lang-bash">sudo systemctl restart jenkins
</code></pre>
<p>Add a stage in the Jenkinsfile.</p>
<pre><code class="lang-groovy">stage('Build Images') {
    steps {
        sh 'docker build -t rakeshpotnuru/productivity-app:client-latest client'
        sh 'docker build -t rakeshpotnuru/productivity-app:server-latest server'
    }
}
</code></pre>
<p>Commit the code and restart the pipeline.</p>
<p><img src="https://i.imgur.com/USh63SD.png" alt="build docker images" width="1984" height="914" loading="lazy">
<em>Build docker images</em></p>
<h3 id="heading-stage-5-push-images-to-the-registry">Stage 5: Push images to the registry</h3>
<p>As a final stage, we will push the images to Docker hub.</p>
<p>Before that, add your docker hub username and password to the Jenkins credentials manager, but for <strong>Kind</strong> choose "Username with password".</p>
<p><img src="https://i.imgur.com/ue0MMKM.png" alt="username with password type credential" width="2010" height="1095" loading="lazy">
<em>Username with password type credential</em></p>
<p>Add the final stage where we login and push images to Docker hub.</p>
<pre><code class="lang-groovy">stage('Push Images to DockerHub') {
    steps {
        withCredentials([usernamePassword(credentialsId: 'dockerhub', passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
            sh 'docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD'
            sh 'docker push rakeshpotnuru/productivity-app:client-latest'
            sh 'docker push rakeshpotnuru/productivity-app:server-latest'
        }
    }
}
</code></pre>
<p><img src="https://i.imgur.com/copfIou.png" alt="push images to dockerhub" width="1991" height="919" loading="lazy">
<em>Push images to dockerhub</em></p>
<p>Here is the complete Jenkinsfile:</p>
<pre><code class="lang-groovy">// This is a Jenkinsfile. It is a script that Jenkins will run when a build is triggered.
pipeline {
    // Telling Jenkins to run the pipeline on any available agent.
    agent any

    // Setting environment variables for the build.
    environment {
        MONGODB_URI = credentials('mongodb-uri')
        TOKEN_KEY = credentials('token-key')
        EMAIL = credentials('email')
        PASSWORD = credentials('password')
    }

    // This is the pipeline. It is a series of stages that Jenkins will run.
    stages {
        // This state is telling Jenkins to checkout the source code from the source control management system.
        stage('Checkout') {
            steps {
                checkout scm
            }
        }

        // This stage is telling Jenkins to run the tests in the client directory.
        stage('Client Tests') {
            steps {
                dir('client') {
                    sh 'npm install'
                    sh 'npm test'
                }
            }
        }

        // This stage is telling Jenkins to run the tests in the server directory.
        stage('Server Tests') {
            steps {
                dir('server') {
                    sh 'npm install'
                    sh 'export MONGODB_URI=$MONGODB_URI'
                    sh 'export TOKEN_KEY=$TOKEN_KEY'
                    sh 'export EMAIL=$EMAIL'
                    sh 'export PASSWORD=$PASSWORD'
                    sh 'npm test'
                }
            }
        }

        // This stage is telling Jenkins to build the images for the client and server.
        stage('Build Images') {
            steps {
                sh 'docker build -t rakeshpotnuru/productivity-app:client-latest client'
                sh 'docker build -t rakeshpotnuru/productivity-app:server-latest server'
            }
        }

        // This stage is telling Jenkins to push the images to DockerHub.
        stage('Push Images to DockerHub') {
            steps {
                withCredentials([usernamePassword(credentialsId: 'dockerhub', passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME')]) {
                    sh 'docker login -u $DOCKER_USERNAME -p $DOCKER_PASSWORD'
                    sh 'docker push rakeshpotnuru/productivity-app:client-latest'
                    sh 'docker push rakeshpotnuru/productivity-app:server-latest'
                }
            }
        }
    }
}
</code></pre>
<p><img src="https://i.imgur.com/NQxFXhO.png" alt="pipeline ran successfully" width="2120" height="1155" loading="lazy">
<em>Pipeline ran successfully</em></p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In summary, let's review what we've covered:</p>
<ul>
<li>We explored the significance of implementing Continuous Integration and Continuous Deployment (CI/CD) in software development.</li>
<li>We delved into the fundamentals of Jenkins and acquired knowledge on how to deploy a Jenkins server on the Azure cloud platform.</li>
<li>We customized Jenkins to meet our specific requirements.</li>
<li>Lastly, we wrote a Jenkinsfile and built a pipeline utilizing the user-friendly interface of Jenkins Blue Ocean.</li>
</ul>
<p>That's all for now! Thanks for reading 🙂.</p>
<p>Connect with me on <a target="_blank" href="https://twitter.com/rakesh_at_tweet">twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ MongoDB Atlas Tutorial – How to Get Started ]]>
                </title>
                <description>
                    <![CDATA[ For the following challenges, you are going to use MongoDB to store data. To simplify the configuration, you'll use a service called MongoDB Atlas. Create a MongoDB Atlas Account MongoDB Atlas is a MongoDB Database-as-a-Service platform, which means ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/</link>
                <guid isPermaLink="false">66c34b395ced6d98e4bd32db</guid>
                
                    <category>
                        <![CDATA[ freeCodeCamp.org ]]>
                    </category>
                
                    <category>
                        <![CDATA[ freeCodeCamp Curriculum ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mongo ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MongoDB ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Thu, 04 Feb 2021 08:12:37 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/601ba92a0a2838549dcbe68a.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>For the following challenges, you are going to use MongoDB to store data. To simplify the configuration, you'll use a service called MongoDB Atlas.</p>
<h2 id="heading-create-a-mongodb-atlas-account">Create a MongoDB Atlas Account</h2>
<p>MongoDB Atlas is a MongoDB Database-as-a-Service platform, which means that they configure and host the database for you. Then, your only responsibility will be to populate your database with what matters: data.</p>
<ul>
<li><a target="_blank" href="https://account.mongodb.com/account/register">Go here</a> to sign up for a new MongoDB Atlas account.</li>
<li>Fill in the registration form with your information and click <strong>Sign up</strong>.</li>
</ul>
<h2 id="heading-create-a-new-cluster">Create a New Cluster</h2>
<ul>
<li>On the next page, fill in your organization's name, project's name, select JavaScript as your preferred programming language, and click the green <strong>Continue</strong> button.</li>
<li>Once you create and verify your account, answer the onboarding questions (your goal, the type of application you're building, your preferred programming language, etc.) and click the green <strong>Finish</strong> button.</li>
<li>On the "Deploy a cloud database" page, click the <strong>Create</strong> button under the Shared cluster type. This should be the only free option:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/05/image-120.png" alt="The &quot;Deploy a cloud database&quot; page showing the free Shared cluster type as last option on the far-right, after the Serverless and Dedicated cluster types." width="600" height="400" loading="lazy"></p>
<ul>
<li>In the <strong>Cloud Provider &amp; Region</strong> dropdown, leave everything as default. Your value there will likely depend on the region you're in.</li>
<li>In the <strong>Cluster Tier</strong> dropdown, leave this as the default, M0 Sandbox (Shared RAM, 512 MB Storage).</li>
<li>In the <strong>Cluster Name</strong> dropdown, you can give your cluster a name, or leave it as the default, Cluster0.</li>
<li>Click the green <strong>Create Cluster</strong> button at the bottom of the screen.</li>
<li>You should now see the message "M0 Cluster Provisioning... This process will take 3-5 minutes." Wait until the cluster is created before going to the next step.</li>
</ul>
<h2 id="heading-create-a-new-user-for-the-database">Create a New User for the Database</h2>
<ul>
<li>On the left side of screen under <strong>SECURITY,</strong> click on <strong>Database Access</strong>.</li>
<li>Click the green <strong>Add New Database User</strong> button.</li>
<li>Under <strong>Authentication Method</strong>, make sure <strong>Password</strong> is selected, then enter in a username and password for your user.</li>
<li>Under <strong>Database User Privileges</strong>, leave this as the default option if there is one – it should be <strong>Read and write to any database</strong>. You may have to select this manually if the default is blank. You can select "Read and write to any database" from the "Add Built In Role" button as shown here:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/02/image--6-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click "Add Built In Role" to select "Read and Write to Any Database".</em></p>
<ul>
<li>Click the <strong>Add User</strong> button to create your new user.</li>
</ul>
<h2 id="heading-allow-access-from-all-ip-addresses">Allow Access From All IP Addresses</h2>
<ul>
<li>On the left side of the screen under <strong>SECURITY</strong>, click on <strong>Network Access</strong>.</li>
<li>Click the green <strong>Add IP Address</strong> button.</li>
<li>In the modal, click the <strong>ALLOW ACCESS FROM ANYWHERE</strong> button. You should see <code>0.0.0.0/0</code> in the Access List Entry field.</li>
<li>Click the green <strong>Confirm</strong> button.</li>
</ul>
<h2 id="heading-connect-to-your-cluster">Connect to Your Cluster</h2>
<ul>
<li>On the left side of the screen under <strong>DEPLOYMENT</strong>, click on <strong>Database</strong>.</li>
<li>Click the <strong>Connect</strong> button for your cluster:</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/05/image-122.png" alt="The Connect button for your cluster, Cluster0 if you left the name as its default." width="600" height="400" loading="lazy"></p>
<ul>
<li>In the popup modal, click on <strong>Connect your application</strong>.</li>
<li>You should see the URI string you'll use to connect to your database similar to this: <code>mongodb+srv://&lt;username&gt;:&lt;password&gt;@&lt;cluster-name&gt;.prx1c.mongodb.net/&lt;db-name&gt;?retryWrites=true&amp;w=majority</code>.</li>
<li>Click the <strong>Copy</strong> button to copy your URI to your clipboard.</li>
</ul>
<p>Notice that the <code>&lt;username&gt;</code> and <code>&lt;cluster-name&gt;</code> fields of the URI you copied are already filled out for you. All you need to do is replace the <code>&lt;password&gt;</code> field with the one you created in the previous step, and be sure to add the name of your database before the query string (<code>?retryWrites=true&amp;w=majority</code>).</p>
<p>You can call your database anything, but it's good to give it a memorable name for your project. For example, if you're working on the "MongoDB and Mongoose" challenges, you could replace <code>&lt;db-name&gt;</code> with <code>fcc-mongodb-and-mongoose</code> or something similar.</p>
<h2 id="heading-connect-to-an-existing-database">Connect to An Existing Database</h2>
<p>If you've already created a cluster and a database and would like to connect it to a new application, follow these steps:</p>
<ul>
<li>On the left side of the screen under <strong>DEPLOYMENT</strong>, click on <strong>Database</strong>.</li>
<li>Find your cluster and click the <strong>Browse Collections</strong> button to see a list of existing databases and collections.</li>
<li>Copy the database name you want to connect to and replace <code>&lt;db-name&gt;</code> with it in the URI string above.</li>
</ul>
<p>And that's it — you now have the URI to add to your application and connect to your database. Keep this URI safe somewhere so you can use it later.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Deploy Mongo on AWS using Docker: the definitive guide for first-timers ]]>
                </title>
                <description>
                    <![CDATA[ By Eric Burel Why you need this? Because JS + Python + Mongo = full data development I am a Meteor developer. More precisely I use Vulcan.js, but that’s a whole other story. Meteor is a full-fledged Node.js framework, pretty nice for SaaS, real-time ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deploy-mongo-on-aws-using-docker-the-definitive-guide-for-first-timers-3738f3babd48/</link>
                <guid isPermaLink="false">66d45e417df3a1f32ee7f82f</guid>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Devops ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ mongo ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 09 Jan 2019 20:01:28 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2019/07/banner_1200_complete.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Eric Burel</p>
<h3 id="heading-why-you-need-this">Why you need this?</h3>
<h4 id="heading-because-js-python-mongo-full-data-development">Because JS + Python + Mongo = full data development</h4>
<p>I am a Meteor developer. More precisely I use Vulcan.js, <a target="_blank" href="https://medium.com/dailyjs/write-less-code-ship-more-apps-how-vulcan-js-makes-me-an-efficient-developer-71c829c76417">but that’s a whole other story</a>. Meteor is a full-fledged Node.js framework, pretty nice for SaaS, real-time apps, prototyping, management softwares and a lot of other use cases.</p>
<p>As a default, it works with MongoDB. MongoDB is a NoSQL database management system (DBMS). It stores documents as JSON and its shell uses JavaScript, which are some reasons why it is so appreciated by Node.js developers.</p>
<p>There is a neat tool called <a target="_blank" href="http://meteor-up.com/">Meteor Up</a> to automatically deploy Meteor apps and the associated Mongo databases on production servers. Neat is actually an understatement, <em>it’s freakin’ awesome.</em></p>
<p>And I am also a Python developer. Python is excellent for web scraping and data science. It’s both easy to use and suited for high performance.</p>
<p>Sometimes, I like to use both Python to extract and process data and Meteor to create the user interface. I call this <strong>“full data development”</strong>, as it goes from the raw data source to the end user interface.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/FTRA0udkWF2CTm79qN6y82lab05vx3Sy-f9S" alt="Image" width="297" height="238" loading="lazy">
<em>The sacred three of the full data developer: Meteor, Mongo, Python</em></p>
<p><strong>But there is a problem:</strong> Meteor Up currently does not expose the Mongo database, only the local Meteor app can connect to it. So I cannot plug my Python servers to my Meteor managed databases out-of-the-box :(</p>
<p>A paid service would do the job by providing an URL for the hosted database, such as this one:</p>
<pre><code>mongo:<span class="hljs-comment">//username:password@somedomain.com:27017</span>
</code></pre><p>But why spend money when you can struggle for hours to set up your own Mongo database on AWS using Docker, and learn tons of useful tricks in the process? <strong>It’s even better if someone, say, me, does it first and writes a lengthy tutorial to make things easier for you!</strong></p>
<p><em>Important note:</em> it’s perfectly fine if it takes you multiple sessions to finish this looong tutorial. Don’t give up! The result is worth the hassle, as mastering Docker and AWS are two skills very appreciated by employers, and very useful in real life. Post your questions as comments if you have any, I’ll do my best to answer all of them.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/g0v26UG99TkEksA8pBDgkjcEzSH9LnLxWe9a" alt="Image" width="600" height="352" loading="lazy"></p>
<h3 id="heading-1-lets-discover-docker">1 — Let’s discover Docker</h3>
<h4 id="heading-our-first-container">Our first container</h4>
<p>I invite you to read <a target="_blank" href="https://docs.docker.com/get-started/">Docker’s official installation doc here</a> and install it, which takes only a few minutes. Then, let’s play a little. Run the following commands in your terminal and observe the results:</p>
<pre><code>docker run --name my-lame-db -d mongo
docker ps
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/xCHkKOqT4f-VdvcBzbllxKAdAvqgcO-1uIDr" alt="Image" width="800" height="143" loading="lazy"></p>
<p>As simple as that, we just created an isolated container that runs Mongo!</p>
<p>You can access the official Mongo image Docker files somewhere <a target="_blank" href="https://github.com/docker-library/mongo">in this folder hosted on GitHub</a> to understand better what happens here. According to the last lines of the <a target="_blank" href="https://github.com/docker-library/mongo/blob/master/4.1/Dockerfile">Dockerfile</a> our db is available on port “27017” as a default:</p>
<pre><code>EXPOSE <span class="hljs-number">27017</span> CMD [<span class="hljs-string">"mongod"</span>]
</code></pre><p>But Mongo exposes itself on this port INSIDE the container. But the container is isolated, so only programs INSIDE the container can talk to Mongo. Our database is up and running but trapped alone in its container :/</p>
<p><strong>That’s lame! Let’s free it!</strong></p>
<h4 id="heading-open-the-container-map-the-ports">Open the container, map the ports</h4>
<p>If you want to access Mongo from OUTSIDE the container, you’ll have to map the exposed port and a port of the machine. The <code>-p</code> option is specifically meant for this:</p>
<pre><code>docker run -p <span class="hljs-number">27017</span>:<span class="hljs-number">27017</span> --name my-local-db -d mongo
</code></pre><p>If you had a Node server, you’d write <code>docker run -p 80:3000 my-node-app</code> for example. Your server running on port 3000 would thus be available through HTTP (port 80). First the container port, then the image port.</p>
<p>Let’s try to access our db in the browser, just for fun:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/xfsKKgSd0F9AGSpXXwrciUTUH2rLwsPrWnPj" alt="Image" width="639" height="145" loading="lazy">
<em>Nice! Our DB is running! You can try <code>docker stop my-awesome-db</code> and <code>docker start my-awesome-db</code> commands. You’ll see this address becoming not available and then available again.</em></p>
<p>As expected, you can’t connect to your db through the browser. But this rejection message comes from Mongo, which is a good sign. Let’s try again using the official CLI tool:</p>
<pre><code>mongo localhost:<span class="hljs-number">27017</span> #or just <span class="hljs-string">"mongo"</span>, <span class="hljs-keyword">as</span> <span class="hljs-built_in">this</span> is the <span class="hljs-keyword">default</span> uri
</code></pre><p><strong>You can access your database shell, we are making progress!</strong></p>
<p>But… I want my database to be on a distant server, not to run locally on my isolated machine.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/7FeX2tR6yc47JAmWRjm6LFt4Y94Mf3iwUE7J" alt="Image" width="600" height="356" loading="lazy"></p>
<h3 id="heading-2-access-aws-from-your-terminal">2 — Access AWS from your terminal</h3>
<p>We picked AWS as our cloud provider because it is widely spread, but keep in mind this is just an example. AWS offers to new users free hosting for 12 months for one server instance, so you don’t need to pay to follow this tutorial. The steps are mostly similar if you pick another hosting service.</p>
<p>First step is to create a programmatic access to Amazon Web Services using the IAM service (Identity and Access Management). This key will be used by Docker Machine (see below) to do some operations, such as creating an AWS EC2 instance for you.</p>
<p>Setting this up is outside the scope of our tutorial. Therefore, I invite you to read <a target="_blank" href="https://blog.codeship.com/running-mean-web-application-docker-containers-aws/">the first part of this article from Vishal Kumar</a>. Follow the first 8 steps until you get AWS credentials. The rest of the article is interesting too but a bit advanced at this point and targeted to the MEAN stack. Let’s focus on Mongo only for the moment.</p>
<p><strong>At this point you should have your credentials.</strong></p>
<pre><code>[<span class="hljs-keyword">default</span>] 
aws_access_key_id = [access key <span class="hljs-keyword">from</span> the downloaded credential file] 
aws_secret_access_key = [secret access key <span class="hljs-keyword">from</span> the downloaded credential file]
</code></pre><p><strong>Keep them safe!</strong> You will have to recreate a key pair if you lose them… and you certainly DON’T want anybody to discover them either!</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/HK4A0Xh2ZoWhu74aTjMdBPjNyPOu9w5J5TXN" alt="Image" width="601" height="373" loading="lazy"></p>
<h3 id="heading-3-put-docker-in-the-cloud-with-docker-machine">3 —Put Docker in the cloud with Docker Machine</h3>
<h4 id="heading-never-need-the-aws-console-again">Never need the AWS console again</h4>
<p>Docker Machine is an utility to manage the different machines hosting your containers (local machines, cloud servers). Hence the name, Docker… Machine. You can set it up for multiple cloud providers and it works very well with AWS.</p>
<p><a target="_blank" href="https://docs.docker.com/machine/drivers/aws/">The official documentation</a> gives all the information you need for AWS. I just jumped the VPC part, it’s a bit too advanced for the moment, but the rest is very useful.</p>
<h4 id="heading-create-the-ec2-instance">Create the EC2 instance</h4>
<p>You will end up writing a command similar to the one below.</p>
<pre><code>docker-machine create \
--driver amazonec2 \
--amazonec2-access-key ***** --amazonec2-secret-key **** \
--amazonec2-region ***** \
--amazonec2-open-port <span class="hljs-number">27017</span> my-awesome-server
</code></pre><p>Let’s break it down.</p>
<ul>
<li>I use the EC2 driver, since I am an AWS user.</li>
<li>I pass the credentials inline as I have multiple accounts to manage</li>
<li>I pass the region where I usually host my apps (“eu-west-3” for me),</li>
<li>Don’t forget to open port 27017 (<code>--amazonec2-open-port 27017</code>), otherwise AWS will block connections even if your container is correctly set.</li>
</ul>
<p>If you did not specify the region correctly, you may have trouble finding your instance on the AWS console. I still don’t get why you can’t have all zones displayed easily in this interface, but that’s how it works.</p>
<p>You should also be able to get rid of the access key and secret key somehow by setting your local machine AWS credentials, or store them as environment variables. I personally prefer to have them in the command line as I may replace them with environment variables.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/mZheBUCZ7JyCgxueh060ejYwNKpetat87YQA" alt="Image" width="800" height="90" loading="lazy"></p>
<p><strong>At this point, you can check the AWS console and see your instance set as expected!</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sKiD1G-AvQe43Ch54y1FXOqT2opVHCGh3wJh" alt="Image" width="600" height="377" loading="lazy"></p>
<h3 id="heading-4-run-a-mongo-container-on-your-instance">4 — Run a Mongo container on your instance</h3>
<h4 id="heading-activate-the-correct-machine">Activate the correct machine</h4>
<p>Now the tricky part, it took me a while to get it right. Docker Machine’s role is to manage your distant machines, launch instances and install Docker on it. That’s all. It’s NOT Docker.</p>
<p>So you still have to use Docker. <strong>But how does Docker know which machine to connect too?</strong></p>
<p>Try this and look at the result:</p>
<pre><code>docker-machine env my-awesome-server
</code></pre><p>It will show a small shell script to setup environment variables.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/YjV8Su28WDjQfeUJOwvqBUj7j-bURkNq5eYb" alt="Image" width="778" height="127" loading="lazy"></p>
<p>It also tells you to run this command:</p>
<pre><code><span class="hljs-built_in">eval</span> $(docker-machine env my-awesome-server)
</code></pre><p>This will simply run the displayed script in your shell. When those env variables are set, your machine becomes “active”.</p>
<p>Type <code>docker-machine active</code> to check that the correct machine is listed.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3ySinraesoaVe-SxlGzHhCjfuueAdzkvRCqv" alt="Image" width="537" height="37" loading="lazy">
<em>\o/</em></p>
<p>Now type <code>docker info</code> , you should see that the <code>Name</code> matches your app. <strong>Magic!</strong> Docker is “connected” to the active machine, configured by Docker Machine.</p>
<p>We can now run the same command as earlier:</p>
<pre><code>docker run -p <span class="hljs-number">27017</span>:<span class="hljs-number">27017</span> --name my-awesome-db -d mongo .
</code></pre><p>It will create the database not on our local machine, but on the distant server. As simple as that!</p>
<p>Run this command to get your machine IP:</p>
<pre><code>docker-machine ip my-awesome-server
</code></pre><p>And open the address <code>http://&lt;ip-given-by-docker-machine&gt;</code>:27017 : you should get a beautiful error message, telling you that you are trying to access MongoDB over HTTPS: it works!!!</p>
<p>Run <code>mongo &lt;ip-given-by-docker-machine&gt;</code>:27017 … <strong>and… you are in ! Congratulations, you just setup your Docker container on a production s</strong>erver.</p>
<p>Ok now, we definitely DON’T want the whole world to access our db, so next step is setting up authentication.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vSa6Azoo6UzMD5zXyH-OuwJLxU0w3Dr0sXKW" alt="Image" width="599" height="289" loading="lazy"></p>
<h3 id="heading-5-setup-authentication-2-containers-solution">5 — Setup authentication — 2 containers solution</h3>
<p>Sorry but you can already delete the container you’ve just created (exercise: I let you figure out the container stopping and removing commands). It was just an example. Sadly, you won’t be able to setup auth with it.</p>
<p>Stay focused because the process is a bit trickier than you would expect:</p>
<ul>
<li>We will create a first container, let’s name it “Container #1”, WITHOUT auth.</li>
<li>We will setup this container so data is saved on the server disk (that’s an important step), create and admin, and delete the container.</li>
<li>We will create a second container, “Container #2” WITH auth. The admin user credentials will still be valid, because they are saved on the disk.</li>
</ul>
<p>There might be simpler solutions I am not yet aware of, for example by providing the admin user credentials during the container creation, so feel free to comment if you are a Docker/Mongo superhero! And a one container solution is also provided in the annexes at the end of the article.</p>
<h4 id="heading-share-data-between-containers">Share data between containers</h4>
<p>At this point you should think “well, containers are isolated, so how can Container #1 and Container #2 share the same admin user”? And you are right. The solution lies in storing files on the server.</p>
<p>Remember when we mapped ports, so that the container’s open port maps Mongo’s port? We will apply the same logic to the file system: we can map folders on the container and folders on the server.</p>
<p>Let’s add an option to our command, and let’s call it the <strong>Final command for Container #1:</strong></p>
<pre><code>docker run \
-d \
-p <span class="hljs-number">27017</span>:<span class="hljs-number">27017</span> \
--name my-awesome-db \
-v ~<span class="hljs-regexp">/dataMongo:/</span>data/db mongo \
mongod
</code></pre><p>Smart! <strong>Now when our Mongo containers will read/write their data in <code>data/db</code> they will also be available to the host server</strong>, in the <code>~/dataMongo</code> folder (host folder first, then container folder).</p>
<h4 id="heading-create-the-admin-user">Create the admin user</h4>
<p>It’s all in the title: you will now connect to your newly created Mongo instance and create the admin user.</p>
<pre><code>docker-machine ip my-awesome-server
mongo &lt;resulting-ip&gt;
</code></pre><p>Now you should be connected to your database shell. You simply need to create a super admin user:</p>
<pre><code>db.createUser(
  {
    <span class="hljs-attr">user</span>: <span class="hljs-string">"admin"</span>,
    <span class="hljs-attr">pwd</span>: <span class="hljs-string">"yourpassword"</span>,
    <span class="hljs-attr">roles</span>: [ { <span class="hljs-attr">role</span>: <span class="hljs-string">"userAdminAnyDatabase"</span>, <span class="hljs-attr">db</span>: <span class="hljs-string">"admin"</span> } ],
    <span class="hljs-attr">passwordDigestor</span> : <span class="hljs-string">"server"</span>
  }
)
</code></pre><p>You can look at the <a target="_blank" href="https://docs.mongodb.com/manual/tutorial/enable-authentication/">official doc</a>, <a target="_blank" href="https://ianlondon.github.io/blog/mongodb-auth/">this article</a> and <a target="_blank" href="https://stackoverflow.com/questions/34559557/how-to-enable-authentication-on-mongodb-through-docker/46645243#comment93826825_46645243">this stack overflow thread</a> for more information.</p>
<p>Also, <a target="_blank" href="https://stackoverflow.com/questions/23943651/mongodb-admin-user-not-authorized">see this thread</a> about the difference between the <code>root</code> role, which is an actual super admin, and <code>userAdminAnyDatabase</code> role, which is a kind of “user creator”.</p>
<h4 id="heading-delete-the-container-and-activate-auth">Delete the container and activate auth</h4>
<p>We can remove Container #1, it’s role was only to let us access a Mongo shell on our server, but it lacked authentication.</p>
<pre><code>docker stop my-awesome-db
docker rm my-awesome-db
</code></pre><p>We can then create our final container, with authentication activated. Since it will be connected to the server file system too, the data created using Container #1 are still available, including our admin user.</p>
<p>We simply add the <code>--auth</code> option to the initial command, it tells Mongo… well, to enable authentication. You guessed right.</p>
<p><strong>Final command for Container #2:</strong></p>
<pre><code>docker run \
-d \
-p <span class="hljs-number">27017</span>:<span class="hljs-number">27017</span> \
--name my-awesome-db \
-v ~<span class="hljs-regexp">/dataMongo:/</span>data/db mongo \
--auth
mongod
</code></pre><p>Now connect again to your Mongo instance and run:</p>
<pre><code>db.createCollection(<span class="hljs-string">'IAMAHACKER'</span>)
</code></pre><p><strong>You’ll get a nice error message as expected!</strong></p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/vPDNkLmy6ItmfpXUyiQp7TkMYU4FrqcBnGC3" alt="Image" width="735" height="146" loading="lazy"></p>
<p>And now try again while being authenticated:</p>
<pre><code>mongo $(docker-machine ip my-awesome-server):<span class="hljs-number">27017</span> -u admin -p yourpassword
</code></pre><p><strong>If it works, you are done! Congratulations ;)</strong></p>
<h3 id="heading-now-what">Now what?</h3>
<p>Your Mongo database is up and running in the cloud, safely isolated in its Docker container, and secured with username/password authentication.</p>
<p>The next steps will be plugging your applications to this database. Remember you can access your server IP using the command <code>docker-machine ip my-awesome-server</code>. You will certainly have to create additional users to administrate your databases.</p>
<p>Also, you probably won’t want anybody to connect to your database shell, even with authentication set. AWS will let you whitelist a few IPs, corresponding to your applications and your own computer, so that only trusted sources can connect to your database.</p>
<p>Below this article, you’ll find a glossary, the final script, and a one-container solution to setup authentication, and a few additional tips.</p>
<p><strong>I hope you found this tutorial helpful!</strong> If it’s the case, don’t forget to clap ;) And please check out the annexes below…</p>
<p><a href="https://twitter.com/LBKE_FR" target="_blank"><img src="https://cdn-media-1.freecodecamp.org/images/HbDwt-Vv483gfb6SdD1uCZQ8YyifxJYOE6AY" width="800" height="160" alt="HbDwt-Vv483gfb6SdD1uCZQ8YyifxJYOE6AY" loading="lazy"></a></p>
<h3 id="heading-annex-1-final-script">Annex 1 — Final script</h3>
<pre><code class="lang-bash"><span class="hljs-comment"># Launch an EC2 instance</span>
docker-machine create \
--driver amazonec2 \
--amazonec2-access-key ***** --amazonec2-secret-key **** \
--amazonec2-region ***** \
--amazonec2-open-port 27017 my-awesome-server
<span class="hljs-comment"># Activate the instance</span>
<span class="hljs-built_in">eval</span> $(docker-machine env my-awesome-server)
<span class="hljs-comment"># Create container 1</span>
docker run \
-d \
-p 27017:27017 \
--name my-awesome-db \
-v ~/dataMongo:/data/db mongo \
mongod
<span class="hljs-comment"># Connect to your DB</span>
mongo $(docker-machine ip my-awesome-server):27017
<span class="hljs-comment"># IN THE MONGO SHELL create a super admin</span>
db.createUser(
  {
    user: <span class="hljs-string">"admin"</span>,
    <span class="hljs-built_in">pwd</span>: <span class="hljs-string">"yourpassword"</span>,
    roles: [ { role: <span class="hljs-string">"userAdminAnyDatabase"</span>, db: <span class="hljs-string">"admin"</span> } ],
    passwordDigestor : <span class="hljs-string">"server"</span>
  }
)
<span class="hljs-comment"># QUIT THE MONGO SHELL</span>
<span class="hljs-comment"># Delete the container and recreate one with auth</span>
docker stop my-awesome-db
docker rm my-awesome-db
<span class="hljs-comment"># Run the final container</span>
docker run \
-d \
-p 27017:27017 \
--name my-awesome-db \
-v ~/dataMongo:/data/db mongo \
--auth \
mongod
<span class="hljs-comment"># IF CA FAILS WITH PERMISSION DENIED ERROR</span>
<span class="hljs-comment"># see https://github.com/kubernetes/minikube/issues/3083</span>
<span class="hljs-comment"># sudo vim /var/lib/snapd/apparmor/profiles/snap.docker.docker</span>
<span class="hljs-comment"># Add following line inside file (e.g alongside with other "owner" lines): </span>
<span class="hljs-comment"># owner @{HOME}/.docker/machine/machines/** r,</span>
<span class="hljs-comment"># sudo apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.docker.docker</span>
</code></pre>
<h3 id="heading-annex-2-neat-tricks-i-wish-i-did-not-have-to-learn-by-myself">Annex 2 — Neat tricks I wish I did not have to learn by myself</h3>
<ul>
<li>If you are in devops, you will eventually get a muscle memory of Docker commands. Otherwise, if you setup projects for production only once a year, WRITE DOWN EVERYTHING. For example, you could write a Medium article.<br>Seriously I’ve lost a few hours of work because I did not write down my progression. The next week I had forgotten everything. Docker is not trivial.</li>
<li>I ran into a permission issue with cert authentication when using Docker Machine, the solution is in the comments of this thread: <a target="_blank" href="https://github.com/kubernetes/minikube/issues/3083">https://github.com/kubernetes/minikube/issues/3083</a></li>
<li><code>docker ps -a</code> will print all containers, <strong>including inactive ones,</strong> while <code>docker ps</code> only prints active containers.</li>
<li>An image is NOT a Dockerfile. <strong>A Dockerfile is a configuration file</strong>. Think of the blueprint of a boat. <strong>An image is a built Docker file.</strong> Think of a boat THAT IS NOT YET in the sea. <strong>A container is an image that you are running.</strong> Think of a boat ROAMING THE SEAS.</li>
</ul>
<p><a target="_blank" href="https://nickjanetakis.com/blog/differences-between-a-dockerfile-docker-image-and-docker-container"><strong>Differences between a Dockerfile, Docker Image and Docker Container</strong></a><br><a target="_blank" href="https://nickjanetakis.com/blog/differences-between-a-dockerfile-docker-image-and-docker-container">_Quick Jump: It All Starts With a Dockerfile | If You Build It, They Will Run (Usually) In casual conversation you may…_nickjanetakis.com</a></p>
<ul>
<li><code>docker pull mongo</code> will for example pull a Mongo Docker image, already built. But how to display the Dockerfile associated? You can’t. If you want to check it, you can look for the relevant GitHub repository (if it exists). That’s the exact same relation between an installed NPM package and its code. <code>npm install</code> does install a build (an “image”) but does not necessarily download the code (a “Dockerfile” here), which usually lives on GitHub but can also be private.</li>
</ul>
<p><a target="_blank" href="https://forums.docker.com/t/how-can-i-view-the-dockerfile-in-an-image/5687/3"><strong>How can I view the Dockerfile in an image?</strong></a><br><a target="_blank" href="https://forums.docker.com/t/how-can-i-view-the-dockerfile-in-an-image/5687/3">_Hi, Looking at some images in the repository (this one, for example: https://hub.docker.com/r/filippobosi/mfi/) I do…_forums.docker.com</a></p>
<ul>
<li>On EC2, your instance IP can change over restarts! You’ll have to regenerate certs to keep connecting to the instance using <code>docker-machine regenerate-certs my-awesome-server</code></li>
</ul>
<h3 id="heading-annex-3-setup-authentication-one-container-solution">Annex 3— Setup authentication — one container solution</h3>
<p>There is also a “one container” solution. It’s less instructive, but faster and requires only one container.</p>
<p>Note : if you already setup auth using the 2 containers approach, you are already done. If you still want to try the 1 container approach, you’ll need to create a new instance on EC2 or remove the <code>~/dataMongo</code> folder of the server.</p>
<p><strong>You still need to share your folders with the host, otherwise your data are tied to the container, which should not happen!</strong> Containers should be easily deletable without any data loss, so documents have to be stored elsewhere.</p>
<p>The idea is to connect to your server and access Mongo from there, instead of accessing Mongo from your local machine. It’s a very subtle difference but that’s what saves us one step.</p>
<p>If you connect to Mongo while being connected to your server, you will have more permission and will be able to setup an admin user even if auth is already set, as Mongo considers you as a “local” user. To rephrase it, since you were able to connect to the machine Mongo is running on, your AWS instance, Mongo already considers you as a “safe” user, as a hacker should not be there in the first place.</p>
<p>Run only the <strong>Final command for Container #2</strong></p>
<pre><code>docker run \
-d \
-p <span class="hljs-number">27017</span>:<span class="hljs-number">27017</span> \
--name my-awesome-db \
-v ~<span class="hljs-regexp">/dataMongo:/</span>data/db mongo \
--auth
mongod
</code></pre><p>You can always ssh your server using <code>docker-machine ssh</code>:</p>
<pre><code>docker-machine ssh my-awesome-server
</code></pre><p>Running <code>mongo</code> will open the Mongo shell. From there, you can add an admin user EVEN is auth is set, as we have done previously.</p>
<h3 id="heading-annex-4-glossary">Annex 4— Glossary</h3>
<p>A bit of devops people mumbling.</p>
<p><strong>AWS:</strong> Amazon Web Services, a famous collection of cloud services with cheap offers.</p>
<p><strong>AWS EC2:</strong> service for hosting server instances. That’s where you’d host your API or your whole website. Note that there might be services more suited for DB hosting but since EC2 is a must-know, it is my choice as a beginner.</p>
<p><strong>Docker:</strong> it’s a… well, a program? In a nutshell that’s a bunch of things that helps you to run programs in containers, isolated from the other programs running on the server, without costing as many resources as a virtual machine. Containers are also helpful to manage services (APIs, databases etc.) on a daily basis: kill/restart it, create new instance in one line…</p>
<p><strong>Container:</strong> that will be my simplified definition, think of a virtual machine without an OS. It provides isolation while not consuming too many computing resources.</p>
<p><strong>Dockerfile:</strong> that’s a config file for docker, which defines all the programs/files/commands/options you need to run your app.</p>
<p><strong>Docker Machine:</strong> a CLI to push your Docker containers where you want, in the cloud or on your own servers.</p>
<p>I am the co-founder of the French company Lebrun Burel Knowledge Engineering (LBKE) — <a target="_blank" href="https://www.lbke.fr">https://www.lbke.fr</a></p>
<p><em>Always happy to talk about code, machine learning, innovation and entrepreneurship!</em></p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
