<?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: Porter</title>
    <description>The latest articles on DEV Community by Porter (@porter).</description>
    <link>https://dev.to/porter</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%2Forganization%2Fprofile_image%2F2809%2Fb6b2cb9d-447a-41f7-acc1-f2fead69c924.png</url>
      <title>DEV Community: Porter</title>
      <link>https://dev.to/porter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/porter"/>
    <language>en</language>
    <item>
      <title>Deploy Strapi on AWS/GCP/Digital Ocean using Porter</title>
      <dc:creator>Trevor Shim</dc:creator>
      <pubDate>Fri, 06 Aug 2021 16:39:42 +0000</pubDate>
      <link>https://dev.to/porter/deploy-strapi-on-aws-gcp-digital-ocean-using-porter-185l</link>
      <guid>https://dev.to/porter/deploy-strapi-on-aws-gcp-digital-ocean-using-porter-185l</guid>
      <description>&lt;h1&gt;
  
  
  Intro
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://porter.run" rel="noopener noreferrer"&gt;Porter&lt;/a&gt; is a Platform as a Service (PaaS) that runs in your own cloud provider. It brings the convenience of platforms like Heroku, Netlify, and Vercel into a cloud provider of your choice. Under the hood, Porter runs on top of a Kubernetes cluster but abstracts away its complexity to the extent that you don't even have to know that it's running on Kubernetes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbk9cevvor7amkjygo05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbk9cevvor7amkjygo05.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a quick guide on how to deploy &lt;a href="https://strapi.io" rel="noopener noreferrer"&gt;Strapi&lt;/a&gt; to a Kubernetes cluster in AWS/GCP/DO using Porter. This guide uses PostgresDB by default - to customize your database settings, modify the files in &lt;code&gt;/app/config/env/production&lt;/code&gt; in the &lt;a href="https://github.com/porter-dev/strapi" rel="noopener noreferrer"&gt;example repository&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quick Deploy
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;Create an account on &lt;a href="https://dashboard.getporter.dev" rel="noopener noreferrer"&gt;Porter&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.porter.run/docs/getting-started-with-porter-on-aws" rel="noopener noreferrer"&gt;One-click provision a Kubernetes cluster&lt;/a&gt; in a cloud provider of your choice, or &lt;a href="https://docs.porter.run/docs/cli-documentation#connecting-to-an-existing-cluster" rel="noopener noreferrer"&gt;connect an existing cluster&lt;/a&gt; if you have one already.&lt;/li&gt;
&lt;li&gt;Fork &lt;a href="https://github.com/porter-dev/strapi" rel="noopener noreferrer"&gt;this repository&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;From the &lt;a href="https://dashboard.getporter.dev/launch" rel="noopener noreferrer"&gt;Launch tab&lt;/a&gt;, navigate to &lt;strong&gt;Web Service &amp;gt; Deploy from Git Repository&lt;/strong&gt;. Then select the forked repository and &lt;code&gt;Dockerfile&lt;/code&gt; in the root directory.&lt;/li&gt;
&lt;li&gt;Configure the port to &lt;code&gt;1337&lt;/code&gt; and set environment variable to &lt;code&gt;NODE_ENV=production&lt;/code&gt;. Depending on your database settings, you might want to add more environment variables. More on this in the section below.&lt;/li&gt;
&lt;li&gt;Set the assigned resources to Strapi's &lt;a href="https://strapi.io/documentation/developer-docs/latest/setup-deployment-guides/deployment.html#general-guidelines" rel="noopener noreferrer"&gt;recommended settings&lt;/a&gt; (i.e. 2048Mi RAM, 1000 CPU), then hit deploy!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyem2y6d5gi4gik45on99.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyem2y6d5gi4gik45on99.png" alt="Screen Shot 2021-08-06 at 11.25.41 AM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying PostgresDB
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Strapi instance deployed through Porter connects to a PostgresDB by default. You can connect Strapi instance deployed on Porter to any external database, but it is also possible to connect to a database that is deployed on Porter. Follow &lt;a href="https://docs.getporter.dev/docs/postgresdb" rel="noopener noreferrer"&gt;this guide to deploy a PostgresDB instance to your cluster in one click&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;After the database has been deployed, navigate to the &lt;strong&gt;Environment Variables&lt;/strong&gt; tab of your deployed Strapi instance. Configure the following environment variables:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NODE_ENV=production
DATABASE_HOST=
DATABASE_PORT=5432
DATABASE_NAME=
DATABASE_USERNAME=
DATABASE_PASSWORD=
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To determine what the correct environment variables are in order to connect to the deployed database, &lt;a href="https://docs.getporter.dev/docs/postgresdb#connecting-to-the-database" rel="noopener noreferrer"&gt;see this guide&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Development
&lt;/h1&gt;

&lt;p&gt;To develop, clone the &lt;a href="https://github.com/porter-dev/strapi" rel="noopener noreferrer"&gt;example repository&lt;/a&gt; to your local environment and run &lt;code&gt;npm install &amp;amp;&amp;amp; npm run develop;&lt;/code&gt; from the &lt;code&gt;app&lt;/code&gt; directory. Porter will automatically handle CI/CD and propagate your changes to production on every push to the repository.&lt;/p&gt;

&lt;h1&gt;
  
  
  Questions?
&lt;/h1&gt;

&lt;p&gt;Join the &lt;a href="https://discord.gg/FaaFjb6DXA" rel="noopener noreferrer"&gt;Porter Discord community&lt;/a&gt; if you have any questions or need help.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>cms</category>
      <category>strapi</category>
      <category>node</category>
    </item>
    <item>
      <title>Datadog on Kubernetes: Avoiding Common Pitfalls</title>
      <dc:creator>Trevor Shim</dc:creator>
      <pubDate>Sat, 17 Jul 2021 00:08:21 +0000</pubDate>
      <link>https://dev.to/porter/datadog-on-kubernetes-avoiding-common-pitfalls-1lgh</link>
      <guid>https://dev.to/porter/datadog-on-kubernetes-avoiding-common-pitfalls-1lgh</guid>
      <description>&lt;p&gt;&lt;a href="https://datadoghq.com"&gt;Datadog&lt;/a&gt; is a powerful monitoring and security platform that gives you visibility into end-to-end traces, application metrics, logs, and infrastructure. While Datadog has &lt;a href="https://docs.datadoghq.com/agent/kubernetes/?tab=helm"&gt;great documentation on their Kubernetes integration&lt;/a&gt;, we've observed that there's some missed nuance that leads to common pitfalls. &lt;/p&gt;

&lt;p&gt;This blog post will guide you through how to install the Datadog agent on Kubernetes and enable additional features such as DogStatsD and APM via Helm and Porter while avoiding these common pitfalls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not running the Datadog Daemonset on all nodes&lt;/li&gt;
&lt;li&gt;Not adding admission label to your application pods you'd like to use DogStatsD and APM with.&lt;/li&gt;
&lt;li&gt;Overriding environment variables that have been injected by the agent &lt;/li&gt;
&lt;li&gt;Not setting resource limits on the agent to avoid crashing the node/kubelet&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Basic Installation
&lt;/h1&gt;

&lt;p&gt;We will use &lt;a href="https://helm.sh"&gt;Helm&lt;/a&gt; to install the Datadog agent with the default set of values. The default values in Datadog's helm chart, along with Datadog's &lt;a href="https://docs.datadoghq.com/agent/kubernetes/integrations/?tab=kubernetes"&gt;Autodiscovery&lt;/a&gt; feature, is sufficient to give visibility into all cluster level metrics.&lt;/p&gt;

&lt;p&gt;These are the commands to install the Datadog agent in your cluster using Helm v3 with the &lt;a href="https://github.com/DataDog/helm-charts/blob/master/charts/datadog/values.yaml"&gt;default values&lt;/a&gt;. Make sure to copy your API key from Datadog dashboard in the install command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add datadog https://helm.datadoghq.com
helm repo update
helm install &amp;lt;RELEASE_NAME&amp;gt; --set datadog.apiKey=&amp;lt;DATADOG_API_KEY&amp;gt; datadog/datadog
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common Pitfall #1: Daemonset not running on all nodes
&lt;/h3&gt;

&lt;p&gt;The Datadog agent is installed as a &lt;a href="https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/"&gt;Daemonset&lt;/a&gt;. This means that the agent is designed to run on every node of your Kubernetes cluster. By default, the Datadog agent will assume that none of your nodes has a taint. If you've added taints to some of your nodes, the agent will run and ingest data only on the nodes that do not have taints.&lt;/p&gt;

&lt;p&gt;To ensure that the agent runs on every node, you must modify the value agents.tolerations to accommodate all your nodes. You can check the taints on your nodes by running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl describe node &amp;lt;NODE_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example, Kubernetes does not run daemonsets on the master node by default. If there is a master node in your cluster and application pods can be scheduled on it, you need to add the following toleration in the agents.tolerations value of the Datadog Helm chart to retrieve metrics from those pods. Make sure to add the appropriate tolerations based on your node taints.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agents:
    tolerations:
    - key: node-role.kubernetes.io/master
      operator: Exists
      effect: NoSchedule
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Enabling DogStatsD and APM
&lt;/h2&gt;

&lt;p&gt;The default installation above exports all cluster level metrics, but you might want to use &lt;a href="https://docs.datadoghq.com/developers/dogstatsd/?tab=hostagent"&gt;DogStatsD&lt;/a&gt; to track custom application metrics and &lt;a href="https://docs.datadoghq.com/tracing/#pagetitle"&gt;APM&lt;/a&gt; to collect application traces. If you've used DogStatsD or APM before without Kubernetes, you are probably used to manually injecting environment variables like &lt;code&gt;DD_AGENT_HOST&lt;/code&gt; for your application code to consume.&lt;/p&gt;

&lt;p&gt;On Kubernetes, the Datadog agent automatically injects &lt;code&gt;DD_AGENT_HOST&lt;/code&gt; as an environment variable into all your containers so you don't have to make additional configuration to export custom metrics. Ensuring that the agent is running on every single node of your cluster is essential to make this work, because the IP address of the pod's host node will be injected.&lt;/p&gt;

&lt;p&gt;To automatically inject these environment variables into your pods, you need to enable the &lt;a href="https://docs.datadoghq.com/agent/cluster_agent/admission_controller/"&gt;Datadog admission controller&lt;/a&gt;. You can do this by modifying these values on the Datadog Helm chart.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clusterAgent:
   admissionController:
      enabled: true
      mutateUnlabelled: false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Common Pitfall #2: Not adding the admission label to your pods
&lt;/h3&gt;

&lt;p&gt;For the admission controller to inject environment variables into your pod, you must add the following label to the pods you'd like to use DogStatsD in:  &lt;code&gt;admission.datadoghq.com/enabled: "true"&lt;/code&gt;. If you'd rather inject the environment variables to all pods running on your cluster, you can also just set the &lt;code&gt;admissionController.mutateUnlabelled&lt;/code&gt; value to &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;You can verify that the environment variable has been injected to the pod by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl exec -it &amp;lt;POD_NAME&amp;gt; -- printenv | grep "DD_AGENT_HOST"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the admission controller is working as expected, you'll see the IP address of the node that the pod is running on. You can confirm this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl describe pod &amp;lt;POD_NAME&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Node&lt;/code&gt; field should match the IP address printed above.&lt;/p&gt;




&lt;h3&gt;
  
  
  Common Pitfall #3: Overriding the injected environment variable
&lt;/h3&gt;

&lt;p&gt;The environment variables injected by the admission controller do not take precedence over the environment variables set on the pod. If you already have &lt;code&gt;DD_AGENT_HOST&lt;/code&gt; defined on the pod, that value will override what's automatically set by the Datadog agent. Make sure to remove both &lt;code&gt;DD_AGENT_HOST&lt;/code&gt; and &lt;code&gt;DD_ENTITY_ID&lt;/code&gt; from your pod configuration for the agent to work as expected.&lt;/p&gt;




&lt;p&gt;Now that you have the admission controller working, modify the following values on the Helm chart to enable DogStatsD and APM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dogstatsd:
   port: 8125
   useHostPort: true
   nonLocalTraffic: true
datadog:
   apm:
     enabled: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Common Pitfall #4: Not setting resource limits on the agent
&lt;/h3&gt;

&lt;p&gt;The default set of values on Datadog do not have any limits set on the resources it can consume. This may result in a node or kubelet crash if the agent consumes more resources than what its host node can accommodate. The resource limit you should set depends on the size of your nodes and the operations you are performing on the agent. There are many places that these resource limits can be set, but we've found that in most cases the agent pod itself is the primary consumer of resources. You can set the limits on the agents with the following values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agents:
   containers:
      agent:
         resources:
            limits:
               cpu: 200m
               memory: 256Mi
            requests:
               cpu: 200m
               memory: 256Mi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then run the install command again with the values above. You can check from your Datadog dashboard whether custom metrics and application traces are being received properly.&lt;/p&gt;




&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;We went over how to install the Datadog agent via Helm and configure additional features like DogStatsD and APM while avoiding common pitfalls. This is the annotated &lt;code&gt;values.yaml&lt;/code&gt; file that you can use as reference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agents:
   containers:
      agent:
         resources:     
            limits:  # &amp;lt;-- set limits on the agent as necessary
            requests:
    tolerations:
    - key: node-role.kubernetes.io/master # &amp;lt;-- Add if nodes have taints
      operator: Exists
      effect: NoSchedule
clusterAgent:
   admissionController:
      enabled: true
      mutateUnlabelled: false # &amp;lt;-- `true` if you want to inject env vars to all pods
datadog:
   apiKey: &amp;lt;API_KEY&amp;gt; # &amp;lt;-- Your api key, can be found in Datadog Dashboard
   apm:
      enabled: true
   logs:
      enabled: true
      containerCollectAll: false # &amp;lt;-- `true` if you want to collect logs from all containers
dogstatsd:
   port: 8125
   useHostPort: true
   nonLocalTraffic: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Installing via Porter
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://porter.run"&gt;Porter&lt;/a&gt; is a platform as a service (PaaS) that runs in your own cloud, specifically in your own Kubernetes cluster. On Porter, you can install the Datadog agent as a one click add-on and enable DogStatsD, APM, and logging by a simple toggle.&lt;/p&gt;

&lt;p&gt;1.Navigate to the launch tab and select the Datadog add-on. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pcxcUHEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3q94hvk9fria3i1ul9zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pcxcUHEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3q94hvk9fria3i1ul9zz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.Put in your ingestion key, toggle the features you'd like to use, then hit deploy!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_Nz9NMX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k016xgrzpt6v57mtov28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_Nz9NMX---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k016xgrzpt6v57mtov28.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>monitoring</category>
      <category>datadog</category>
    </item>
    <item>
      <title>Deploy Django on Kubernetes in a few clicks (without even Dockerizing your application)</title>
      <dc:creator>Trevor Shim</dc:creator>
      <pubDate>Mon, 07 Jun 2021 22:08:49 +0000</pubDate>
      <link>https://dev.to/porter/deploy-django-on-kubernetes-in-a-few-clicks-without-even-dockerizing-your-application-3nd1</link>
      <guid>https://dev.to/porter/deploy-django-on-kubernetes-in-a-few-clicks-without-even-dockerizing-your-application-3nd1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This blog article is based on the &lt;a href="https://docs.getporter.dev/docs/django" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; and &lt;a href="https://github.com/jimcru21/porter-sample-django-non-docker" rel="noopener noreferrer"&gt;example repository&lt;/a&gt; written by Porter's community member, &lt;a href="https://github.com/jimcru21" rel="noopener noreferrer"&gt;jimcru21&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt; is a powerful container orchestrator that automates deployments, management, and scaling of containerized applications. Despite all these benefits of Kubernetes, however, there is typically a ton of overhead to it that is often not justified for simple applications. In this tutorial, we go over how to deploy Django applications on major cloud providers' Kubernetes offerings (e.g. EKS, GKE, DOKS) in a few clicks using Porter, without even having to containerize your applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Porter?
&lt;/h2&gt;

&lt;p&gt;Porter is a Platform as a Service (PaaS) that runs in the user's own cloud. If you're familiar with Heroku/Vercel/Netlify, Porter brings the ease of use of those platforms into your own cloud, particularly into your own Kubernetes cluster. With Porter, you can deploy and scale Django applications on Kubernetes with minimal overhead without having to write a &lt;code&gt;Dockerfile&lt;/code&gt; or &lt;code&gt;YAML&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Porter is open source.&lt;/strong&gt; Check out the source code &lt;a href="https://github.com/porter-dev/porter" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provisioning the Kubernetes Cluster
&lt;/h2&gt;

&lt;p&gt;Before you can start deploying a Django application on Kubernetes, you must first provision a Kubernetes cluster. With Porter, it's possible to create a cluster on AWS, GCP, and Digital Ocean with a single click. Follow &lt;a href="https://docs.getporter.dev/docs/getting-started-with-porter-on-aws" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to provision the cluster in the cloud provider of your choice.&lt;/p&gt;

&lt;p&gt;Alternatively, you can also provision a cluster on your own and connect Porter to an existing cluster. These are the guides on how to create your own cluster for each cloud provider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/create-cluster.html" rel="noopener noreferrer"&gt;Amazon Web Services&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/kubernetes-engine/docs/quickstart" rel="noopener noreferrer"&gt;Google Cloud Platform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.digitalocean.com/products/kubernetes/quickstart/" rel="noopener noreferrer"&gt;Digital Ocean&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After you've created a Kubernetes cluster, you can connect to it via the Porter CLI per &lt;a href="https://docs.getporter.dev/docs/linking-an-existing-docker-container-registry" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare Django Application
&lt;/h2&gt;

&lt;p&gt;While it is not necessary to containerize your Django application to deploy it through Porter, you must follow these steps for a successful deployment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;django-allow-cidr&lt;/code&gt; (this is the middleware to enable the use of CIDR IP ranges in &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt;)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install django-allow-cidr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Go to Django Settings and add &lt;code&gt;os.environ.get&lt;/code&gt; in allowed host.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", default='127.0.0.1').split(" ")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add allowed CIDR networks. Put CIDR according to the Kubernetes kubelet CIDR. If you've provisioned the cluster through Porter, it is set to 10.99.0.0/16 by default. If you've provisioned the cluster yourself, visit your cloud console to find the CIDR.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALLOWED_CIDR_NETS = os.environ.get("ALLOWED_CIDR_NETS", default='10.99.0.0/16').split(" ")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add &lt;code&gt;django-allow-cidr&lt;/code&gt; middleware to the application.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MIDDLEWARE = [
  'allow_cidr.middleware.AllowCIDRMiddleware',
  #'django.middleware.security.SecurityMiddleware',
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add Gunicorn.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install gunicorn
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add static folder and add your HTML and CSS files. Locate static URL settings and add static file dirs below:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;STATICFILES_DIRS = (
  os.path.join(BASE_DIR, 'static'),
)
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a &lt;code&gt;Procfile&lt;/code&gt; to your repository. This is an alternative configuration to &lt;code&gt;Dockerfile&lt;/code&gt; that uses &lt;a href="https://buildpacks.io" rel="noopener noreferrer"&gt;Cloud Native Buildpacks&lt;/a&gt;, which have been popularized by Heroku. Porter uses the &lt;code&gt;Procfile&lt;/code&gt; to build your images if a &lt;code&gt;Dockerfile&lt;/code&gt; is not present.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lastly, generate a requirements file.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip freeze &amp;gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Sample repository for the above configuration: &lt;a href="https://github.com/jimcru21/porter-sample-django-non-docker" rel="noopener noreferrer"&gt;https://github.com/jimcru21/porter-sample-django-non-docker&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Deploy Django on Porter
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Visit the Porter Dashboard. Click &lt;strong&gt;Web Service &amp;gt; Launch Template&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Name your application.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya1151vnfxtc7pnoymr8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fya1151vnfxtc7pnoymr8.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When prompted for the deployment method, click Git Repository. Connect your GitHub account and select the repo you'd like to deploy from. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzov9jjto2u4zj7kdn5lc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzov9jjto2u4zj7kdn5lc.png" alt="image"&gt;&lt;/a&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the branch (&lt;code&gt;main&lt;/code&gt; in the example below), then hit Continue.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnadwx53xje52m79srf51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnadwx53xje52m79srf51.png" alt="image"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmyhamgsrtxizlq41fgf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmyhamgsrtxizlq41fgf6.png" alt="image"&gt;&lt;/a&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Porter will read your &lt;code&gt;Procfile&lt;/code&gt; and prompt you for the name of the process you'd like to run. In the example above, the process is named &lt;code&gt;web&lt;/code&gt;. By default, Porter stores your build artifacts in the registry that was provisioned by Porter. If you've connected to an existing cluster, you can also connect an existing container registry to Porter using our CLI per &lt;a href="https://docs.getporter.dev/docs/linking-an-existing-docker-container-registry" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Additional settings, specify the container port that you use for &lt;code&gt;gunicorn&lt;/code&gt; in the &lt;code&gt;Procfile&lt;/code&gt; (in the example above, this is set to &lt;code&gt;8989&lt;/code&gt;). You can also configure custom domain per &lt;a href="https://docs.getporter.dev/docs/https-and-custom-domains" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;From the &lt;strong&gt;Environment&lt;/strong&gt; tab, set &lt;code&gt;DJANGO_ALLOWED_HOSTS&lt;/code&gt; that we specify on Django settings. Then input the domain you have set for your application.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxt2omu56fxamm52wxi18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxt2omu56fxamm52wxi18.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click &lt;strong&gt;Deploy&lt;/strong&gt; then wait for buildpack to finish and push to porter. Porter writes a GitHub Actions file to your repository for Continuous Integration. You can check the build progress on your GitHub repository under the &lt;strong&gt;Action&lt;/strong&gt; tab.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Done!
&lt;/h2&gt;

&lt;p&gt;Kubernetes can be a mountain to climb for newcomers, but many developers are drawn to its benefits despite the steep learning curve. Porter is a tool that eases that learning process to the extent that the user doesn't have to learn anything about Kubernetes, or even Docker, to get started.&lt;/p&gt;

&lt;p&gt;If you have any questions about this tutorial, &lt;a href="https://discord.gg/FaaFjb6DXA" rel="noopener noreferrer"&gt;join our discord community&lt;/a&gt; and ask away!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>webdev</category>
      <category>django</category>
      <category>docker</category>
    </item>
    <item>
      <title>Introducing Porter - move your localhost into the cloud</title>
      <dc:creator>Trevor Shim</dc:creator>
      <pubDate>Wed, 05 Aug 2020 16:17:16 +0000</pubDate>
      <link>https://dev.to/porter/introducing-porter-move-your-localhost-into-the-cloud-17c1</link>
      <guid>https://dev.to/porter/introducing-porter-move-your-localhost-into-the-cloud-17c1</guid>
      <description>&lt;p&gt;&lt;em&gt;Think Heroku meets Codespaces. A quick tutorial on how to get started on Porter with a simple MERN stack.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnypi3epv1431t1ehjndn.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnypi3epv1431t1ehjndn.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up development environments and deploying them into production are probably the two biggest wastes of time of any development cycle. Configuring and installing modules on your local machine often goes wrong, and we have all experienced the headache of trying to deploy an application that works on your own machine but breaks in production. &lt;/p&gt;

&lt;p&gt;With platforms like Vercel and Netlify, developing and deploying JAM stack applications are getting easier and easier. But what if you want to work on something more complex that requires multiple databases, caches, and workers? Heroku and Render do a better job automating a lot of the DevOps when you are working on more complex projects, but you still have to do the work of maintaining a development environment on your local machine and shipping it to production.&lt;/p&gt;

&lt;p&gt;What if, instead, development happened in the cloud so that you don't have to run or install anything on your local machine? What if you could ship your application into production with a single click from the same platform you were developing on?&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Porter?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Porter is a platform that lets you develop applications in the cloud while using your favorite local IDE. You can also host the apps you've developed on Porter with a single click from the same platform.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;If you are familiar with Heroku, you can think of apps on Porter as Dynos you can directly develop in. This means your localhost now lives on a URL that you can publicly share, and your application's entire lifecycle from development to production happens on a single platform with no local set-up whatsoever. &lt;/p&gt;

&lt;p&gt;Let's see this in action with a simple MERN stack example.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Create Containers
&lt;/h1&gt;

&lt;p&gt;Everything that runs on Porter runs as Docker containers. If you aren't familiar with containers, you can think of them as lightweight VM's that are completely isolated from your host machine. These containers let you develop and ship code in consistent and predictable environments. In Heroku terms, containers behave a lot like Dynos, except Dynos were created before Docker came around and ate up the software industry. Porter is a modern PaaS (Platform as a Service) &lt;em&gt;built on top of the Docker ecosystem&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;First, login to the &lt;a href="https://dashboard.getporter.dev" rel="noopener noreferrer"&gt;Porter Dashboard&lt;/a&gt;. You will be prompted to create a project, then you will see the "Create a Container" button. When you click that button, you will see a variety of templates Porter provides by default. To spin up a MERN stack, simply select the React and MongoDB templates as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fosfngi83t8qjozxmck3f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fosfngi83t8qjozxmck3f.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It may take up to a minute for these containers to load. Once they've loaded, each container will display a URL. &lt;strong&gt;This URL effectively acts as your localhost.&lt;/strong&gt; In the case of the react container, the URL serves a simple &lt;code&gt;create-react-app&lt;/code&gt; template as shown here: &lt;a href="https://dev-to-react-porter-dev-bwxork4w.getporter.dev/" rel="noopener noreferrer"&gt;https://dev-to-react-porter-dev-bwxork4w.getporter.dev/&lt;/a&gt; (Note that this URL is my development environment!).&lt;/p&gt;

&lt;p&gt;In the case of the mongo container, the URL is a connection string that other containers can access as long as they are within the same project. We'll come back to this later.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Download the Porter CLI
&lt;/h1&gt;

&lt;p&gt;I may have lied a little bit when I said you don't have to install anything on your local machine. You do need to install one tiny CLI to start developing in these remote containers, but I promise this is the only thing you'll need to install.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g porter-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command is for MacOS. For Windows and Linux, check &lt;a href="https://docs.getporter.dev/docs/cli-documentation" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Porter lets you develop on remotely running containers without having to use a WebIDE. You can use whatever local editor you want to use. Our CLI will sync your local files with the files in the remote container so that every local edit you make gets propagated into the remote container.&lt;/p&gt;

&lt;p&gt;First, login via the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;porter login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create and navigate to an empty local directory and run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;porter init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will prompt you to select a container you want to link your local directory with. Select the name of the react container you have just created. &lt;/p&gt;

&lt;p&gt;Once you have linked up the directory, you can start syncing your local file system with the remote container via&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;porter sync --bi-dir
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will start a bi-directional syncing process and download all the contents in the remote container into your local folder. Now, every change you make on your local directory will be instantly propagated into the remote container, and the container URL will hot-reload whenever there's a change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fflpb3z10z6l375t2k4d3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fflpb3z10z6l375t2k4d3.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To see the logs from the &lt;code&gt;create-react-app&lt;/code&gt; process running inside the container, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;porter logs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  3. Linking up MongoDB
&lt;/h1&gt;

&lt;p&gt;Spinning up an entirely new MongoDB instance is arbitrary on Porter. If you want to start fresh, just make a new instance by clicking on the MongoDB template again. The connection string displayed on the container is available only to internal traffic - i.e. only the other containers that are within the same project can access this database. Copy this connection string by clicking on the icon boxed below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbo3wryj67gnk9lfugvah.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fbo3wryj67gnk9lfugvah.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To connect to database, you need to first &lt;code&gt;npm install mongodb --save&lt;/code&gt; in the react container. To install new modules in this container, you simply need to run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;porter enter sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open up a shell inside the remote container, and you can run the commands you'd normally run on your local machine inside this remote shell, such as &lt;code&gt;npm install&lt;/code&gt;. These kinds of commands might require more RAM and CPU than what is assigned to the container by default. You can allocate more resources from the "Resources" tab in container setting.&lt;/p&gt;

&lt;p&gt;Now, you can use this connection string from the react container to connect to the database. To test the connection, let's go back to &lt;code&gt;/index.js&lt;/code&gt; in the react container and add these lines of code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var MongoClient = require('mongodb').MongoClient

// Connection URL you have copied
var url = 'mongodb://mongo-db-0.mongo-db.porter-dev-bwxork4w:27017/';

MongoClient.connect(url, function(err, db) {
  console.log("Connected successfully to mongodb");

  db.close();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdp5m5zs7xtpz86guscyh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdp5m5zs7xtpz86guscyh.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see the log message that confirms that proper connection has been established between the react and mongodb containers.&lt;/p&gt;

&lt;h1&gt;
  
  
  4. Using environment variables on Porter
&lt;/h1&gt;

&lt;p&gt;Instead of using &lt;code&gt;.env&lt;/code&gt; files, you can directly inject in environment variables into the container via the Porter Dashboard. As an example, click on the react container and navigate to the "Environment" tab. Write in a new &lt;code&gt;MONGO_URL&lt;/code&gt; variable with the URL that you have copied from the mongodb container. The container will restart, and when you swap out the connection string and &lt;code&gt;console.log&lt;/code&gt; the connection string, you will see the URL in the logs as you'd expect.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var MongoClient = require('mongodb').MongoClient

MongoClient.connect(process.env.MONGO_URL, function(err, db) {
  console.log(process.env.MONGO_URL);
  console.log("Connected successfully to mongodb");

  db.close();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the logs, you will see that the connection has been established once again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcqlgzfy68gpo2d9t4zer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcqlgzfy68gpo2d9t4zer.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Try it out!
&lt;/h1&gt;

&lt;p&gt;You can try setting up a simple MERN stack on Porter for free here: &lt;a href="https://dashboard.getporter.dev" rel="noopener noreferrer"&gt;https://dashboard.getporter.dev&lt;/a&gt;. Here are the &lt;a href="https://docs.getporter.dev" rel="noopener noreferrer"&gt;docs&lt;/a&gt; for your reference. &lt;/p&gt;

&lt;p&gt;We can't wait to see the projects you create on Porter!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F54ocriaenuh5qf1a5ymn.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F54ocriaenuh5qf1a5ymn.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>webdev</category>
      <category>docker</category>
      <category>react</category>
    </item>
    <item>
      <title>Wordpress Development on Porter</title>
      <dc:creator>Trevor Shim</dc:creator>
      <pubDate>Mon, 03 Aug 2020 23:26:52 +0000</pubDate>
      <link>https://dev.to/porter/wordpress-development-on-porter-3419</link>
      <guid>https://dev.to/porter/wordpress-development-on-porter-3419</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jZOAmVoF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3y0w0h0sa86kmg3i8coa.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jZOAmVoF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3y0w0h0sa86kmg3i8coa.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Local development for Wordpress often requires a lot of configuration and installation of tools like PhpMyAdmin, MySQL, and Wordpress itself. Docker helps compartmentalize each of these components with &lt;strong&gt;containers&lt;/strong&gt;. Simply put, containers are lightweight VM’s that provide environments that are isolated from your host machine — if you are familiar with heroku, you can think of them as Dynos. Docker lets you spin up and manage Wordpress stacks for your various projects without the headache of maintaining and configuring these technologies on your computer.&lt;/p&gt;

&lt;p&gt;Despite Docker’s ease of use, however, there is still a bit of learning curve that prevent Wordpress developers from taking advantage of containers. Porter lets you develop Wordpress themes and plugins using Docker, without having to configure &lt;strong&gt;or even install&lt;/strong&gt; Docker.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Porter?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Porter is a remote development environment that lets you develop Docker containers in the cloud while using a local IDE of your choice.&lt;/strong&gt; Using the Wordpress template provided on Porter, you can start developing themes and plugins without configuring or installing anything locally, then ship them into production &lt;em&gt;with literally one-click&lt;/em&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  1. Create containers on Porter
&lt;/h1&gt;

&lt;p&gt;Everything on Porter runs as Docker containers. Let’s create Wordpress and MySQL containers on Porter using the default templates. You can do this by logging into Porter’s &lt;a href="https://dashboard.getporter.dev"&gt;dashboard&lt;/a&gt;, then clicking on the “Create a Container” button and choosing the corresponding templates.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oxrF_nuS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nz46jwjy6r2jhlpjc4as.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oxrF_nuS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nz46jwjy6r2jhlpjc4as.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
It may take up to a minute for these containers to load.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. Connect the containers
&lt;/h1&gt;

&lt;p&gt;Once you have created these containers, you need to make them talk to each other — this can be done by changing the environment variables of each container. Click on the MySQL container you have created and change the environment variables &lt;code&gt;MYSQL_ROOT_PASSWORD&lt;/code&gt;, &lt;code&gt;MYSQL_DATABASE&lt;/code&gt;, &lt;code&gt;MYSQL_USER&lt;/code&gt;, &lt;code&gt;MYSQL_PASSWORD&lt;/code&gt; to values of your choice from the “Environment” tab. All variables are initially set to "default”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TDvipxxx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k4vy56lnm7bjl7e9qj6i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TDvipxxx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/k4vy56lnm7bjl7e9qj6i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have configured the MySQL container, copy the connection string displayed in the container by clicking on the icon boxed below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tZMpnX3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dgmhjwxoc5aa23bfy34b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tZMpnX3E--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/dgmhjwxoc5aa23bfy34b.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now click on the Wordpress container, then change the environment variable &lt;code&gt;WORDPRESS_DB_HOST&lt;/code&gt; from “default” to the connection string you have just copied — make sure &lt;code&gt;WORDPRESS_DB_PASSWORD&lt;/code&gt; also matches the &lt;code&gt;MYSQL_ROOT_PASSWORD&lt;/code&gt; you have put in the MySQL container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--nzbO7JzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nbpqen2hilzt8t0fbxy4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--nzbO7JzR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nbpqen2hilzt8t0fbxy4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you hit save, the Wordpress container will restart and soon the URL on the container will display the familiar Wordpress installation page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ft7gJqQq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s8gk8ib4piktmxtyp8dk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ft7gJqQq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s8gk8ib4piktmxtyp8dk.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Develop on remote containers
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;The above URL is now effectively your localhost&lt;/strong&gt;. But how do you develop on these remotely running containers? All you need to install is the &lt;code&gt;porter-cli&lt;/code&gt; that will let you develop remotely using your own local IDE by &lt;em&gt;syncing your local files with the files in the remote container&lt;/em&gt;. Let’s see this in action.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Install the CLI with &lt;code&gt;npm i -g porter-cli&lt;/code&gt; if you are using MacOS. For other OS, see our &lt;a href="https://docs.getporter.dev/docs/cli-documentation"&gt;docs&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;porter login&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q6tmvn-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7a5fmzsgn0qbetzsvb4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q6tmvn-4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7a5fmzsgn0qbetzsvb4u.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Make an empty local directory and run &lt;code&gt;porter init&lt;/code&gt; inside that directory. When prompted to choose a container, select the name of the Wordpress container you have created.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run &lt;code&gt;porter sync --bi-dir&lt;/code&gt; from the same directory — this will start a bi-directional syncing process between the directory and your remote container.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---pAQfUox--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x83rig4nz0yfvv9kx0gq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---pAQfUox--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/x83rig4nz0yfvv9kx0gq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Once all the folders have been downloaded from the remote-container via sync, start developing your themes in the &lt;code&gt;wp-content/themes&lt;/code&gt; directory that has just been downloaded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Any local edit you make in that local directory will be instantly propagated into the remote container that you can view on the above URL. As long as the syncing process is ongoing, the remote container will behave exactly like your localhost. Just run &lt;code&gt;porter sync --bi-dir&lt;/code&gt; again when you want to start developing.&lt;/p&gt;

&lt;p&gt;You can share your works in progress with clients and collaborators by simply giving them the URL you are developing on. The containers you develop on Porter can also be &lt;strong&gt;promoted to production&lt;/strong&gt; with your custom domain in just one-click.&lt;/p&gt;

&lt;p&gt;You can try developing Wordpress themes on Porter for free &lt;a href="https://dashboard.getporter.dev"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>wordpress</category>
      <category>showdev</category>
      <category>docker</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
