<?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: Paul Arah</title>
    <description>The latest articles on DEV Community by Paul Arah (@paularah).</description>
    <link>https://dev.to/paularah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F307749%2Ff127e4e5-d322-4556-9934-6ae50dccce41.jpeg</url>
      <title>DEV Community: Paul Arah</title>
      <link>https://dev.to/paularah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paularah"/>
    <language>en</language>
    <item>
      <title>Container Networking - The Docker Way</title>
      <dc:creator>Paul Arah</dc:creator>
      <pubDate>Sat, 04 Feb 2023 23:02:24 +0000</pubDate>
      <link>https://dev.to/paularah/container-networking-the-docker-way-1ffb</link>
      <guid>https://dev.to/paularah/container-networking-the-docker-way-1ffb</guid>
      <description>&lt;p&gt;Containers put together a couple of features of the Linux kernel to achieve isolation. Since containers are inherently isolated from their host and other containers on the same host, there needs to be some networking mechanism that facilitates communication between containers and the host network interface. At the core of it, that's essentially what container networking is. This post focuses on how docker does it; the networking parts of docker we tend to run into daily as developers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;N/B:&lt;/strong&gt; I am using a Linux machine. The demo might have slight differences if you use a Mac or Windows. This is mostly because docker containers on windows and mac run inside a Linux VM. Most container networking concepts directly map to regular networks, so basic familiarity with networking concepts would be helpful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Containers
&lt;/h3&gt;

&lt;p&gt;When you create a docker container, it lives in an isolated network namespace and is unreachable from the outside world. We can test this out by creating a container running Apache web server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// creates a container with Apache httpd running in it
$ docker run -dit --rm --network none  --name my-container httpd

// inspects the container and formats for the networks settings
$ docker inspect -f '{{json .NetworkSettings}}' my-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we inspect the container for its networking details, we see it has no IP address or way to reach it. This is because containers are designed to work exactly like this. Containers isolate resources like the file system, networking, processes and memory at the OS level.&lt;br&gt;
Notice we passed a --network flag to none when creating the container. This disables docker networking features. As much as we want isolation, In many cases, we wouldn't want our containers to be unreachable, and docker provides a couple of networking options called drivers to cater to this. We'll focus on bridge and host drivers, as these are the two most common drivers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//list the available docker networks
$ docker network ls 
  NETWORK ID     NAME      DRIVER    SCOPE
26fb9b15153b   bridge    bridge    local
19a78c13e726   host      host      local
705da40f3ea2   none      null      local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Default Bridge Network
&lt;/h3&gt;

&lt;p&gt;We create a container, docker uses the default bridge network. The default bridge network allows containers within the same network and host to communicate. We can try this by stopping our container, restarting it without a network option and inspecting its networking settings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sidenote:&lt;/strong&gt; I recently figured out the docker inspect command can be, for lack of a better description "overloaded or variadic". Meaning docker inspect command works without explicitly specifying what docker object we're inspecting. So we don't have explicitly say something like docker container inspect my-container. Docker automatically figures out if the object we're inspecting is a container, network or volume. Cool developer experience, innit?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker run -dit --rm  --name my-container httpd
$ docker inspect my-container 

"Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "26fb9b15153b91f9ed246b24f400f614f90e6f8f954c2b8f3682ada020a6f55a",
                    "EndpointID": "d1ed5ca3766b6abe731d43cdaf6bf085c35a84021b6adef6d1b7e47f6c3e1a5f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that the container is now attached to the default bridge network. The container is assigned an IPv4 address by default, this can be configured to use IPv6 instead. We can reach the container directly by its IP address from our host(I haven't tried this out, but it's very likely that by default, you wouldn't be able to reach the container by its IP address directly from the host if you're on Mac or Windows).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// apache runs by default on port 80, no need to specify the port.
$ curl 172.17.0.2
&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;It works!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  User-defined Bridge Networks
&lt;/h3&gt;

&lt;p&gt;As the name implies, user-defined bridge networks are bridge networks we create and can configure ourselves. The default bridge network is great and provides a finer level of network isolation, but we still lose out on a couple of great features of docker bridge networks when we stick to the default bridge network. Docker recommends we always create our own bridge networks. Working with user-defined bridge networks is quite intuitive. We can create, configure and delete networks. We can also connect and disconnect containers from a network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// creates a brige network - by default docker uses the brigde driver 
$ docker network create my-net

// delete a network 
docker network rm my-net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we inspect the network, we see that there are currently no containers attached to it. We can connect and disconnect containers to the network on the fly.&lt;br&gt;
To try this out, we will create a busybox container in addition to the Apache httpd container running and connect them to the same network.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// creates a container from busybox image 
$ docker run -dit --rm --network my-net  --name busybox busybox

//connects the Apache web server to the my-net network
$ docker network connect my-net my-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we inspect the my-net network now, both containers are listed. Since both containers are on the same bridge network, we can easily reach one container from the other.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker exec -it busybox /bin/sh
$ ping my-container
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice we're pinging the container by its name, my-container? A DNS entry is created for the container name and IP address, allowing easy service discovery. Containers are somewhat ephemeral, and the IP addresses are bound to change. This saves us the hassle of dealing with dynamic IP addresses.&lt;/p&gt;

&lt;p&gt;We can map a port from the container to the host. This is called port forwarding. ThIS way, we can reach the container from the host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//  -p flag maps port 80 on the container to port 3000
$ docker run -dit --rm --network none -p 3000:80  --name my-container httpd
$ curl localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Host Network
&lt;/h3&gt;

&lt;p&gt;The host network driver removes the isolation between the host and the container. The container now directly relies on the host network. This means it doesn't get a network stack or IP address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// creates a container using the host network driver docker run -dit --rm --network host --name my-container httpd
docker run -dit --rm --network host --name my-container httpd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can reach our containers directly on the localhost without port forwarding.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl localhost
&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;It works!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Overlay Network
&lt;/h3&gt;

&lt;p&gt;An honourable mention here is the overlay network driver. This network type plays an important role in how multi-host systems like our favourite container orchestration tools works. Docker swarm leverages this to connect multiple hosts, and Kubernetes infamously leverages the same concept for a VLAN that spans the cluster nodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bare-bones Container Networking Internals&lt;/strong&gt;&lt;br&gt;
Docker networks create a great abstraction over the underlying network stack, If you're interested in the low-level Linux details independent of a container runtime, Ivan Velichko has a great blog &lt;a href="https://iximiuz.com/en/posts/container-networking-is-simple/" rel="noopener noreferrer"&gt;post&lt;/a&gt; on bare-bones container networking.&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>developer</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Deploy and automatically provision SSL certs on a Node.js server with Traefik and Docker.</title>
      <dc:creator>Paul Arah</dc:creator>
      <pubDate>Wed, 07 Jul 2021 00:31:33 +0000</pubDate>
      <link>https://dev.to/paularah/deploy-and-automatically-provision-ssl-certs-on-a-node-js-server-with-traefik-and-docker-2j0e</link>
      <guid>https://dev.to/paularah/deploy-and-automatically-provision-ssl-certs-on-a-node-js-server-with-traefik-and-docker-2j0e</guid>
      <description>&lt;p&gt;In this tutorial, we would learn to deploy Node.js servers with docker on a Linux-based VPS and automatically provision SSL certificates with Traefik.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic familiarity with Node.js, docker and docker-compose.&lt;/li&gt;
&lt;li&gt;A virtual private server with a public IP address from any cloud service provider of your choice.
&lt;/li&gt;
&lt;li&gt;A domain or subdomain and a corresponding DNS record pointing the public IP address of your VPS. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Traefik is an open-source, cloud-native reverse proxy. A reverse proxy essentially sits in front your servers and handles incoming clients request. So instead your client request directly going to your Node.js server, the request first goes through Traefik and Traefik then forwards it to your server. This allows us do things like SSL encryption, canary deploys, load balancing among others. &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%2Frbqqdbxhw8wc4lgxh9gt.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%2Frbqqdbxhw8wc4lgxh9gt.png" alt="traefik demo image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now lets get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Spin Up a Linux VPS
&lt;/h3&gt;

&lt;p&gt;This could be an Amazon EC2 instance, A digital ocean droplet, Linode VMs, etc or even an on-prem Linux machine with publicly accessible IP address. For this demo, I am using an ubuntu digital ocean droplet. &lt;/p&gt;

&lt;h3&gt;
  
  
  Install docker and docker compose.
&lt;/h3&gt;

&lt;p&gt;This tutorial focuses on the deployment phase. You can read the docker docs on how to install &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;docker&lt;/a&gt; and &lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;docker compose&lt;/a&gt; for your respective platforms. &lt;/p&gt;

&lt;h3&gt;
  
  
  Firewall restrictions
&lt;/h3&gt;

&lt;p&gt;Depending your VPS and setup ensure that both port 80 and port 443 are accessible from outside. This could mean adjusting the inbound rules of your security group in your VPC on AWS or opening the ports on ufw. &lt;/p&gt;

&lt;h3&gt;
  
  
  DNS records
&lt;/h3&gt;

&lt;p&gt;If you haven't done so already, create a DNS record for your domain or sub-domain and point it to the public IP address of your VPS. You can confirm the DNS propagation by pinging your domain and seeing that it resolves to the IP address of your VPS. If you use a DNS provider like cloudfare that supports proxying, you might want to turn off this feature while testing.&lt;/p&gt;

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

ping mydomian.com // should resolve to your VPS IP address


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Node.js Server
&lt;/h3&gt;

&lt;p&gt;In this example, I will be demonstrating using a simple fastify server. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;


&lt;span class="c1"&gt;//server.js file &lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fastify&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fastify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)({&lt;/span&gt; &lt;span class="na"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;fastify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world! I'm using fastify&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fastify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fastify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nf"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Dockerise Node.js server
&lt;/h3&gt;

&lt;p&gt;We containerise our Node.js server with docker using the Dockerfile below. &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="s"&gt;FROM node:12-alpine&lt;/span&gt;
&lt;span class="s"&gt;RUN mkdir home/node-traefik&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /home/node-traefik&lt;/span&gt;
&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN npm install&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;
&lt;span class="s"&gt;CMD [ "node", "server.js" ]&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;N/B: This is a basic example on how to dockerise a Node.js App. For production use cases, you should probably read the  Node.js and Docker best practices guide &lt;a href="https://github.com/goldbergyoni/nodebestpractices#8-docker-best-practices" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Compose
&lt;/h3&gt;

&lt;p&gt;Now we create a docker-compose file and reference our Dockerfile. At this stage we can start our Node.js server with the &lt;code&gt;docker-compose up&lt;/code&gt; command. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;node-server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Configuring Traefik
&lt;/h3&gt;

&lt;p&gt;To introduce Traefik into our flow, we create a new service for Traefik in our docker-compose file.  &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;reverse-proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik:v2.4&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik"&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--api.insecure=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--api.dashboard=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--api.debug=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--providers.docker=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--log.LEVEL=DEBUG"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--entryPoints.web.address=:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--entryPoints.websecure.address=:443"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--providers.docker.exposedbydefault=false"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.httpchallenge=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.email=hello@paularah.com"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./letsencrypt:/letsencrypt"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Traefik has the concept static and dynamic configurations. Static configuration are needed by Traefik at startup time and if changes are made to the static configurations, Traefik has to be restarted for these changes to take effect. When using Traefik with docker-compose, we define static configurations as commands in the docker-compose file.&lt;/p&gt;

&lt;p&gt;Lets go through each command in the static configuration individually.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;- "--providers.docker=true"&lt;/code&gt; tells traefik that docker is our key infrastructure components and thus traefik queries the docker API for the relevant information it needs. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--api.insecure&lt;/code&gt; enables the traefik dashboard in insecure mode. For production uses cases, you want to use basic authentication and TLS on the dashboard. &lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;- "--providers.docker.exposedbydefault=false"&lt;/code&gt; tells traefik not to expose a service unless being explicitly to do so. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The mounted volume with&lt;code&gt;- "/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/code&gt; allows Traefik to communicate with docker. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;- "--entryPoints.web.address=:80"&lt;/code&gt; and &lt;code&gt;- "--entryPoints.websecure.address=:443"&lt;/code&gt; line declare a network and corresponding port entry points into Traefik.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;"--certificatesresolvers.myresolver.acme.email=hello@paularah.com&lt;/code&gt; creates a certificate resolver named &lt;code&gt;myresolver&lt;/code&gt;. The certificate resolver is responsible for generating, renewing and disposing certificates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;- "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"&lt;/code&gt; Tells our certificate resolver to save our certificates in acme.json file in the letsencrypt volume.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;- "--certificatesresolvers.myresolver.acme.httpchallenge=true"&lt;/code&gt; Tells the certificate resolver to use the HTTP challenge. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the this stage, if we start up our containers, the Traefik dashboard will be accessible on port 8080&lt;code&gt;http://&amp;lt;IP&amp;gt;:8080&lt;/code&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%2Fq94grfz6yqnph2jfvv7i.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%2Fq94grfz6yqnph2jfvv7i.png" alt="sample traefik dashobaord"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our Node.js server services has not been linked to Traefik yet. This is where the concept of dynamic configuration comes in. Unlike static configurations, dynamic configurations can be updated after Traefik has started. Traefik watches for changes in the dynamic configurations and applies it with no need to restart Traefik. When using Traefik with docker, we add dynamic configurations by using labels. Traefik reads these meta-data and applies it to the respective service. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

 &lt;span class="na"&gt;node-server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node-server&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.enable=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.node-server.rule=Host(`play.paularah.com`)"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.node-server.entrypoints=websecure"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.node-server.tls.certresolver=myresolver"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.redirs.rule=hostregexp(`{host:.+}`)"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.redirs.entrypoints=web"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.redirs.middlewares=redirect-to-https"&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Since we configured Traefik not to expose services except being explictly told to do so, The &lt;code&gt;- "traefik.enable=true"&lt;/code&gt; label now exposes our Node.js server container to Traefik.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;- "traefik.http.routers.node-server.rule=Host(play.paularah.com)"&lt;/code&gt; creates a router that routes network request from the domian &lt;code&gt;play.paularah.com&lt;/code&gt; to the Node.js server container. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;- "traefik.http.routers.node-server.tls.certresolver=myresolver"&lt;br&gt;
&lt;/code&gt; tells the router to use the certificate resolver we created earlier. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"&lt;/code&gt; creates a middleware to force-redirect HTTP network request to HTTPS. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next three labels creates a router that matches every request to the host on port 80 and then uses the redirect to https middleware we created previously. &lt;/p&gt;

&lt;p&gt;Restarting the containers now and voila! our Node.js server is now available from &lt;code&gt;play.paularah.com&lt;/code&gt;, uses SSL and force redirects to HTTPS. &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Traefik makes deploying HTTP servers with docker really easy. We can deploy multiple projects on the same host, by simply adding more services to our docker-compose file. One major advantage of this setup of is having all our configurations in one place and in a single command &lt;code&gt;docker-compose up&lt;/code&gt; everything is up and running. This also makes our entire setup easily reproducible and allowing us move a project easily from one cloud service provider to another.  &lt;/p&gt;

&lt;p&gt;The source code for this blogpost can be found at &lt;a href="https://github.com/paularah/node-traefik" rel="noopener noreferrer"&gt;https://github.com/paularah/node-traefik&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>node</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Easy JavaScript Toolchain Management with Volta</title>
      <dc:creator>Paul Arah</dc:creator>
      <pubDate>Tue, 20 Apr 2021 04:20:58 +0000</pubDate>
      <link>https://dev.to/paularah/easy-javascript-toolchain-management-with-volta-2imb</link>
      <guid>https://dev.to/paularah/easy-javascript-toolchain-management-with-volta-2imb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Summary:&lt;/strong&gt; Use &lt;a href="https://volta.sh"&gt;Volta&lt;/a&gt; for managing everything JavaScript. It's easy, flexible and convenient.  &lt;/p&gt;

&lt;p&gt;A common problem JavaScript developers face is managing multiple versions of the toolchain we use. Toolchain here refers to Node.js, NPM, TypeScript and everything in between you'd use for working with JavaScript. &lt;/p&gt;

&lt;p&gt;I personally have had scenarios where I'd install the needed dependencies for a project and then discover the project isn't compatible with the version of my global installation of Node.js. I'd then have to delete the dependencies, flush my cache, install the right version of Node.js, then install the dependencies for the project all over again.&lt;/p&gt;

&lt;p&gt;This begs the question, how do we seamlessly manage different versions of your toolchain across different projects?&lt;/p&gt;

&lt;p&gt;Volta to the rescue! Volta is a hassle-Free JavaScript tool manager. Volta allows you easily switch between multiple versions of your toolchain depending on the project requirement. Your team can define a specific version of the toolchain for a project and this stays consistent for everyone making your environment easily reproducible. &lt;/p&gt;

&lt;p&gt;To install volta on UNIX-based systems(macOS &amp;amp; Linux).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://get.volta.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Close your current shell session and open a new one for the changes Volta made to fully take place.&lt;/p&gt;

&lt;p&gt;For Windows, download and run the &lt;a href="https://github.com/volta-cli/volta/releases/download/v1.0.3/volta-1.0.3-windows-x86_64.msi"&gt;Windows installer&lt;/a&gt; and follow the instructions.&lt;/p&gt;

&lt;p&gt;To install Node.js &amp;amp; NPM&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volta &lt;span class="nb"&gt;install &lt;/span&gt;node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have Node.js globally available. You can specify the version of Node else it automatically defaults to the LTS version. &lt;/p&gt;

&lt;h2&gt;
  
  
  Managing your Toolchain Across Projects
&lt;/h2&gt;

&lt;p&gt;To pin a specific version of Node.js to a project, run the command below in the root directory of the project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;volta pin node@12
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Checking for the node version outside the project directory would give you the version of your global installation when you originally installed node with volta. Navigating into the project directory and checking the node version would give the node version specific for this project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$cd&lt;/span&gt; home/some-js-project 
&lt;span class="nv"&gt;$volta&lt;/span&gt; pin node@12
&lt;span class="nv"&gt;$node&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="c"&gt;#gives you node version 12 &lt;/span&gt;
&lt;span class="nv"&gt;$cd&lt;/span&gt; ../
node &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="c"&gt;#gives you node version 14&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assuming your global installation of the typescript compiler is version 4.2 and your project uses version 3.2. Volta automatically detects manages this for you.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$npm&lt;/span&gt; i typescript &lt;span class="nt"&gt;-g&lt;/span&gt;
tsc &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="c"&gt;#4.2&lt;/span&gt;
&lt;span class="nv"&gt;$cd&lt;/span&gt; some-js-project
&lt;span class="nv"&gt;$tsc&lt;/span&gt; &lt;span class="nt"&gt;--version&lt;/span&gt; &lt;span class="c"&gt;#3.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, volta works by replacing your global node command with a &lt;a href="https://en.wikipedia.org/wiki/Shim_(computing)"&gt;shim&lt;/a&gt; that downloads the right version of your tools for you. Volta is written in rust and shipped as a single binary, thus it's very lightweight with a small overhead. There are also Github actions for it, making it easy to use in your CI. If you need to extend the functionality of Volta, volta has some advanced features like hooks that allow you do this. &lt;/p&gt;

&lt;p&gt;Volta works out of the box with no stress. Now we can go back to doing more important things like frying eggs and cooking Jollof Rice.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Dependency Injection In JavaScript</title>
      <dc:creator>Paul Arah</dc:creator>
      <pubDate>Fri, 26 Mar 2021 02:03:49 +0000</pubDate>
      <link>https://dev.to/paularah/dependency-injection-in-javascript-1bfk</link>
      <guid>https://dev.to/paularah/dependency-injection-in-javascript-1bfk</guid>
      <description>&lt;p&gt;Writing code that is resilient in the face of changing requirements needs an intentional application of techniques that achieve this goal. In this article, we'll explore dependency injection as one of those techniques. &lt;br&gt;
Take a look at the code snippet below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function retrieves a resource across the network using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;Fetch API&lt;/a&gt; and returns it. While this works, from a clean and maintainable code perspective, there are quite a number of things that could go wrong here. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If our requirements change in the future and we decide to replace the Fetch API with say another HTTP client like &lt;a href="https://github.com/axios/axios"&gt;Axios&lt;/a&gt;, we would have to modify the whole function to work with Axios. &lt;/li&gt;
&lt;li&gt;The Fetch API is a global object in the browser and isn't available or might not work exactly as intended in an environment like Node.js where we would be running our test. &lt;/li&gt;
&lt;li&gt;When testing we might not want to actually retrieve the resource from across the network, but there's currently no way to do that.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where dependency injection comes into play. At the core of it, dependency injection is giving the dependency(s) our code needs from the outside rather than allow our code to directly construct and resolve the dependencies as we have done in the example above. We pass in the dependencies our code needs as a parameter to the getData function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resourceData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://myresourcepath&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;//do something with resourceData&lt;/span&gt;
&lt;span class="p"&gt;})()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intent behind dependency injection is to achieve separation of concerns. This makes our code more modular, reusable, extensible and testable.  &lt;/p&gt;

&lt;p&gt;At the core of javascript are objects and prototypes, so we can do dependency injection the functional or object-oriented way. Functional programming features of javascript like &lt;a href="https://blog.bitsrc.io/understanding-higher-order-functions-in-javascript-75461803bad"&gt;higher-order functions&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;closures&lt;/a&gt; allow us implement dependency injection elegantly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchResource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fetchResource function takes an instance of our HTTP client and returns a function that accepts the URL parameter and makes the actual request for the resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://mybasepath&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchResource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;httpClient&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/resourcepath&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We replaced the native fetch with Axios, and everything still works without meddling with the internal implementation. In this case, our code doesn't directly depend on any specific library or implementation. As we can easily substitute for another library. &lt;/p&gt;

&lt;p&gt;The object(function in this case) receiving the dependency is often referred to as the client, and the object being injected is referred to as the service. &lt;/p&gt;

&lt;p&gt;A service might require different configurations across the codebase. Since our client doesn't care about the internal implementation or configuration of a service, we can preconfigure a service differently as we've done above. &lt;/p&gt;

&lt;p&gt;Dependency injection enables us to isolate our code(business logic) from changes in external components like libraries, frameworks, databases, ORMs, etc. With proper separation of concerns, testing becomes easy and straightforward. We can &lt;a href="https://en.wikipedia.org/wiki/Method_stub"&gt;stub&lt;/a&gt; out the dependencies and test our code for multiple ideal and edge cases independent of external components. &lt;/p&gt;

&lt;p&gt;In more complex use cases, usually bigger projects, doing dependency injection by hand is simply not scalable and introduces a whole new level of complexity. We can leverage the power of dependency injection containers to address this. Loosely speaking, dependency injection containers contain the dependencies and the logic to create these dependencies. You ask the container for a new instance of a service, it resolves the dependencies, constructs the object and returns it back. &lt;/p&gt;

&lt;p&gt;There are a number of Javascript dependency injection container libraries out there. Some of my personal favourites are &lt;a href="https://github.com/typestack/typedi"&gt;TypeDI&lt;/a&gt; and &lt;a href="https://github.com/inversify/InversifyJS"&gt;InversifyJS&lt;/a&gt;. Here is an example demonstrating basic usage of Typedi with JavaScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;typedi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ExampleClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I am alive!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="cm"&gt;/** Request an instance of ExampleClass from TypeDI. */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;classInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ExampleClass&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/** We received an instance of ExampleClass and ready to work with it. */&lt;/span&gt;
&lt;span class="nx"&gt;classInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;print&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The technique of dependency injection cuts across different programming languages. As a general rule of thumb, dependency injection can be done with languages that allow the passing of functions and objects as parameters. Some popular HTTP frameworks like &lt;a href="https://docs.nestjs.com/providers#dependency-injection"&gt;NestJs&lt;/a&gt; and &lt;a href="https://fastapi.tiangolo.com/tutorial/dependencies/"&gt;FastAPI&lt;/a&gt; come with an in-built dependency injection system. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
