<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Robert Cooper</title>
    <description>The latest articles on Forem by Robert Cooper (@robertcoopercode).</description>
    <link>https://forem.com/robertcoopercode</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%2F28226%2F55fd6110-4550-42f5-b992-c1bee747b215.jpg</url>
      <title>Forem: Robert Cooper</title>
      <link>https://forem.com/robertcoopercode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/robertcoopercode"/>
    <language>en</language>
    <item>
      <title>Docker guide</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Sun, 18 Oct 2020 20:22:33 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/docker-guide-118i</link>
      <guid>https://forem.com/robertcoopercode/docker-guide-118i</guid>
      <description>&lt;p&gt;The purpose of this guide is to explain the &lt;em&gt;most important concepts&lt;/em&gt; related to Docker to be able to &lt;strong&gt;effectively work with Docker&lt;/strong&gt; for application development purposes.&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; is a tool that helps run applications in isolated environments.&lt;/p&gt;

&lt;p&gt;There has always been a need to make sure applications can run in isolated environments for applications to run as expected on different machines/servers. This is important to be able to develop applications on a local machine and have them run as expected in a deployed environment. It's also important for developers to be able to run applications as expected on any computer to get up and running quickly and collaborate with other developers no matter how they've configured their computer.&lt;/p&gt;

&lt;p&gt;The reason why running applications on different machines is so difficult is that all the right versions of an application's dependencies must be installed for it to run as expected. For example, if trying to run an API that is built with Node.js, and it was developed and tested on a machine using Node.js 12.8, it might not necessarily run the same on a machine that has Node.js version 10.18 installed. The same goes for any other dependency used in applications, such as python, ruby, php, typescript, nginx, apache, mysql, postgres, etc. Docker makes it possible to build containerized applications that hold the right versions of all dependencies and can run as intended on different machines.&lt;/p&gt;

&lt;p&gt;Docker has 4 types of "objects" it uses to be able to create these isolated environments: &lt;strong&gt;images&lt;/strong&gt;, &lt;strong&gt;containers&lt;/strong&gt;, &lt;strong&gt;volumes&lt;/strong&gt;, and &lt;strong&gt;networks&lt;/strong&gt;. The two objects users will most often be directly working with are Docker &lt;strong&gt;images&lt;/strong&gt; and Docker &lt;strong&gt;containers&lt;/strong&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%2F87enruxj6demk8u0h0m4.jpg" 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%2F87enruxj6demk8u0h0m4.jpg" alt="Docker objects: images, containers, volumes, and networks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker images&lt;/strong&gt; contain the code that is needed to run an application and &lt;strong&gt;Docker containers&lt;/strong&gt; are the isolated environments that are running the code from Docker images. A Docker &lt;em&gt;image&lt;/em&gt; can be thought of as the blueprints and code used by a Docker &lt;em&gt;container&lt;/em&gt;. Docker images can be saved to image registries for others to download the images. The most popular Docker image registry is &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;. You can think of image registries as the NPM equivalent for Docker images.&lt;/p&gt;

&lt;p&gt;Read more about Docker images and containers in the &lt;em&gt;Docker images&lt;/em&gt; and &lt;em&gt;Docker containers&lt;/em&gt; sections of the guide, respectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker volumes&lt;/strong&gt; are used to persist data that is generated by running Docker containers. By saving data to a Docker volume, it will permit an application to have the same data even if the Docker container has been removed, recreated, or restarted. Docker volumes are also useful if two different containers should have access to the same data since both containers can point to the same volume.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker networks&lt;/strong&gt; are used to make sure containers are isolated from each other and are also used to allow containers to communicate with each other.&lt;/p&gt;

&lt;p&gt;Read more about Docker volumes and networks in the &lt;em&gt;Docker volumes&lt;/em&gt; and &lt;em&gt;Docker networks&lt;/em&gt; sections of the guide, respectively.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/get-started/overview/" rel="noopener noreferrer"&gt;&lt;em&gt;"Docker Overview"&lt;/em&gt;&lt;/a&gt; from the official Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What about virtual machines?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Virtual_machine" rel="noopener noreferrer"&gt;Virtual machines&lt;/a&gt; (VMs) often come up in the same conversation as Docker since they are both be used to create isolated environments.&lt;/p&gt;

&lt;p&gt;With Docker, applications run in isolated environments called containers and each one of these containers share the same operating system &lt;a href="https://en.wikipedia.org/wiki/Kernel_(operating_system)" rel="noopener noreferrer"&gt;kernel&lt;/a&gt; on a machine. On the other hand, applications that run on virtual machines run in their own operating system and don't share an underlying kernel. Virtual machines operate with the help of a &lt;a href="https://geek-university.com/oracle-virtualbox/what-is-hypervisor/" rel="noopener noreferrer"&gt;hypervisor&lt;/a&gt; which is responsible for managing which operating system to run.&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%2F8o0fcmsh7muy2s4j67oz.jpg" 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%2F8o0fcmsh7muy2s4j67oz.jpg" alt="Type 1 Hypervisors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Type 1 Hypervisors (Paravirtualization): Hypervisor sits on bare metal hardware and each OS sits on the hypervisor. e.g. &lt;a href="https://www.vmware.com/ca/products/esxi-and-esx.html" rel="noopener noreferrer"&gt;VMware ESXi&lt;/a&gt;, &lt;a href="https://www.oracle.com/ca-en/virtualization/vm-server-for-x86/" rel="noopener noreferrer"&gt;Oracle VM Server&lt;/a&gt;, &lt;a href="https://docs.microsoft.com/en-us/windows-server/virtualization/hyper-v/hyper-v-technology-overview" rel="noopener noreferrer"&gt;Microsoft Hyper-V&lt;/a&gt;&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%2Fli9ic38rv3peuqoo9mmf.jpg" 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%2Fli9ic38rv3peuqoo9mmf.jpg" alt="Type 2 Hypervisors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Type 2 Hypervisors (Emulation): Hypervisor sits on top of the host OS. e.g. &lt;a href="https://www.virtualbox.org/" rel="noopener noreferrer"&gt;Oracle VirtualBox&lt;/a&gt;, &lt;a href="https://www.parallels.com/ca/" rel="noopener noreferrer"&gt;Parallels&lt;/a&gt;, &lt;a href="https://www.vmware.com/ca/products/workstation-pro.html" rel="noopener noreferrer"&gt;VMware Workstation&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note: Linux kernel is fundamentally used&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To run Linux Docker containers, a Linux kernel needs to be present on the machine. Docker handles this for you if you install the Docker Desktop app for Mac OS or Windows, which ships with &lt;a href="https://github.com/Linuxkit/Linuxkit" rel="noopener noreferrer"&gt;LinuxKit&lt;/a&gt;: a lightweight Linux kernel that runs on Mac OS or Windows operating systems and is used by the Docker engine. The lightweight Linux kernel sits on a hypervisor that ships natively with Windows (&lt;a href="https://stackoverflow.com/a/41556921/8360496" rel="noopener noreferrer"&gt;reference&lt;/a&gt;) and Mac OS (&lt;a href="https://stackoverflow.com/a/55085366/8360496" rel="noopener noreferrer"&gt;reference&lt;/a&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%2Fknhzd8lybbsyldrf7hy0.jpg" 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%2Fknhzd8lybbsyldrf7hy0.jpg" alt="Docker hardware and software breakdown on Linux, Mac OS, and Windows OS"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The advantages of using Docker over virtual machines overwhelmingly tip the scales in favor of using Docker. Compared to virtual machines, Docker containers can get up in running within seconds compared to minutes, are lightweight (magnitude of MBs compared to GBs), are easily configurable, and use a small amount of resources. Perhaps the only reason to use a virtual machine over docker is if a high level of isolation is desired because of concerns about security vulnerabilities associated with having Docker containers using a shared kernel on the host operating system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://geek-university.com/oracle-virtualbox/what-is-hypervisor/" rel="noopener noreferrer"&gt;Explanation of the types of hypervisors&lt;/a&gt; by Geek University&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://geekflare.com/docker-vs-virtual-machine/#:~:text=The%20docker%20containers%20are%20suited,then%20virtual%20machines%20are%20required." rel="noopener noreferrer"&gt;Explanation of the pros and cons of Docker and Virtual Machines&lt;/a&gt; by Geekflare&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.docker.com/resources/what-container#/package_software" rel="noopener noreferrer"&gt;Explanation of Docker containers and the differences between containers and virtual machines&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackoverflow.com/questions/16047306/how-is-docker-different-from-a-virtual-machine" rel="noopener noreferrer"&gt;&lt;em&gt;"How is Docker different from a virtual machine?"&lt;/em&gt;&lt;/a&gt; question on Stack Overflow with many useful answers, including &lt;a href="https://stackoverflow.com/a/36368012/8360496" rel="noopener noreferrer"&gt;this one&lt;/a&gt; defining paravirtualization and emulation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker engine
&lt;/h2&gt;

&lt;p&gt;The Docker engine needs to be installed and running on any machine that wants to do anything related to Docker. Starting the engine means that a long-running background process (the Docker daemon which also corresponds with the &lt;code&gt;dockerd&lt;/code&gt; command) gets started to create a server that can be interacted with via a REST API. The Docker CLI is the way most people interact with the REST API to manage Docker objects, but 3rd party apps are also able to interact &lt;a href="https://docs.docker.com/engine/api/latest" rel="noopener noreferrer"&gt;directly with the REST API&lt;/a&gt; or via &lt;a href="https://docs.docker.com/engine/api/sdk/" rel="noopener noreferrer"&gt;Docker engine SDKs&lt;/a&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%2Ft24gp0054hjuwy0gp96o.jpg" 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%2Ft24gp0054hjuwy0gp96o.jpg" alt="Docker engine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/" rel="noopener noreferrer"&gt;&lt;em&gt;"Docker Engine overview"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing Docker
&lt;/h2&gt;

&lt;p&gt;The easiest way to install all Docker related dependencies is to install &lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt;. Docker Desktop comes with several Docker related tools including the Docker Engine, Docker CLI, and Docker Compose CLI (read about Docker Compose here).&lt;/p&gt;

&lt;p&gt;Docker Desktop is available for download on &lt;strong&gt;Mac&lt;/strong&gt; and &lt;strong&gt;Windows&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/docker-for-mac/install/" rel="noopener noreferrer"&gt;Mac download&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/docker-for-windows/install/" rel="noopener noreferrer"&gt;Windows download&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once the above is installed, ensure that the Docker Desktop is running. If the Docker Desktop is running it means that the Docker engine is running and the Docker CLI commands mentioned in this guide will be able to be executed.&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%2F95azhw29fzntrqmkd3nj.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%2F95azhw29fzntrqmkd3nj.png" alt="Docker Desktop is running indicator"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Indication in the Mac OS menu bar that Docker Desktop is running.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For &lt;strong&gt;Linux&lt;/strong&gt; users, there is no Docker Desktop, so each component must be installed individually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Docker Engine + CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/install/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On Linux, the Docker daemon must be started using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command should work since &lt;code&gt;systemctl&lt;/code&gt; ships with &lt;em&gt;most&lt;/em&gt; Linux distributions, but if not, use &lt;code&gt;sudo service docker start&lt;/code&gt;. There is also a way to &lt;a href="https://docs.docker.com/engine/install/Linux-postinstall/#configure-docker-to-start-on-boot" rel="noopener noreferrer"&gt;automatically have Linux start Docker on system boot&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;&lt;em&gt;"Docker Desktop overview"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;Dockerfile&lt;/code&gt; is a file that holds the instructions on how to build an image. The file generally begins by specifying a base image that will be used as the basis of the Docker image to be built. For example, if building a python based API, a base image that is made up of a Linux OS with python installed on it can be used. After specifying a base image, other instructions are used that can specify the following details on how to the Docker image should be built:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment variables to set in a container&lt;/li&gt;
&lt;li&gt;Ports exposed by the image&lt;/li&gt;
&lt;li&gt;Which files should be copied into the image&lt;/li&gt;
&lt;li&gt;Which dependencies should be installed&lt;/li&gt;
&lt;li&gt;Command to be executed when starting a container (e.g. &lt;code&gt;yarn start&lt;/code&gt; if starting a Node.js API)&lt;/li&gt;
&lt;li&gt;And more...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an example, an image for a Node.js API might have a &lt;code&gt;Dockerfile&lt;/code&gt; similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Base image that has Node version 12.16.1 installed on a Linux OS.&lt;/span&gt;
&lt;span class="c"&gt;# This is an alpine Linux image that is smaller than the non-alpine Linux equivalent images.&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:12.16.1-alpine3.11&lt;/span&gt;

&lt;span class="c"&gt;# Installs some dependencies required for the Node.js API&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; make g++

&lt;span class="c"&gt;# Indicates that the API exposes port 3000&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;

&lt;span class="c"&gt;# Specifies the working directory. All the paths referenced after this point will be relative to this directory.&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="c"&gt;# Copy all local source files into the Docker container's working directory&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Installs NPM dependencies using yarn&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;yarn &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Command to start the API which will get executed when a Docker container using this image is started.&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "yarn", "start" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Frequently used instructions are described in the table below. The full list of instructions can be found in the &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile reference&lt;/a&gt; documentation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Instruction&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#from" rel="noopener noreferrer"&gt;&lt;code&gt;FROM&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Defines a base image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#run" rel="noopener noreferrer"&gt;&lt;code&gt;RUN&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Executes command in a new image layer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#cmd" rel="noopener noreferrer"&gt;&lt;code&gt;CMD&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Command to be executed when running a container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#expose" rel="noopener noreferrer"&gt;&lt;code&gt;EXPOSE&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Documents which ports are exposed (not used for anything other than documentation)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#env" rel="noopener noreferrer"&gt;&lt;code&gt;ENV&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Sets environment variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#copy" rel="noopener noreferrer"&gt;&lt;code&gt;COPY&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Copies files/directories into the image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#add" rel="noopener noreferrer"&gt;&lt;code&gt;ADD&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;A more feature-rich version of the &lt;code&gt;COPY&lt;/code&gt; instruction. &lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#add-or-copy" rel="noopener noreferrer"&gt;&lt;code&gt;COPY&lt;/code&gt; is preferred&lt;/a&gt; over &lt;code&gt;ADD&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#entrypoint" rel="noopener noreferrer"&gt;&lt;code&gt;ENTRYPOINT&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Define a container's executable. See the difference between the &lt;code&gt;CMD&lt;/code&gt; instruction &lt;a href="https://phoenixnap.com/kb/docker-cmd-vs-entrypoint" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#volume" rel="noopener noreferrer"&gt;&lt;code&gt;VOLUME&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Defines which directory in an image should be treated as a volume. The volume will be given a random name which can be found using &lt;code&gt;docker inspect&lt;/code&gt; command.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#workdir" rel="noopener noreferrer"&gt;&lt;code&gt;WORKDIR&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Defines the working directory for subsequent instructions in the &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/engine/reference/builder/#arg" rel="noopener noreferrer"&gt;&lt;code&gt;ARG&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Defines variables that can be passed by the &lt;code&gt;docker build --build-arg&lt;/code&gt; command and used within the &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If some files should be prevented from being copied into the Docker image, a &lt;code&gt;.dockerignore&lt;/code&gt; file can be added at the same level as the &lt;code&gt;Dockerfile&lt;/code&gt; where files that should not be copied over into the Docker image can be specified. This means that if using a &lt;code&gt;COPY&lt;/code&gt; or &lt;code&gt;ADD&lt;/code&gt; instruction in a &lt;code&gt;Dockerfile&lt;/code&gt; to specify the files to be added into a Docker image, any file specified in the &lt;code&gt;.dockerignore&lt;/code&gt; file will be ignored and not added into the Docker image. This may be desirable to prevent files that contain sensitive information (e.g. &lt;code&gt;.env&lt;/code&gt; files that hold API keys) or large unnecessary files from being added to a Docker image. &lt;a href="https://docs.docker.com/engine/reference/builder/#dockerignore-file" rel="noopener noreferrer"&gt;Make sure to know the correct syntax to use&lt;/a&gt; when specifying files to be ignored in the &lt;code&gt;.dockerignore&lt;/code&gt; file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Use Alpine Linux base images&lt;/p&gt;

&lt;p&gt;Many base images have an &lt;a href="https://alpineLinux.org/" rel="noopener noreferrer"&gt;Alpine Linux&lt;/a&gt; equivalent which is much smaller than their non-apline equivalent. Building smaller Docker images is advantageous because you can save money on data transfer/storing costs associated with Docker images. For example, Amazon's container registry service, ECR, &lt;a href="https://aws.amazon.com/ecr/pricing/" rel="noopener noreferrer"&gt;charges users per GB&lt;/a&gt; of Docker images that are pulled from their registry. Smaller Docker images also mean pulling Docker images from image registries will be done more quickly, which can have noticeable effects on your CI times and local development wait times.&lt;/p&gt;

&lt;p&gt;Learn more about the advantages of Alpine Linux images by reading &lt;a href="https://nickjanetakis.com/blog/the-3-biggest-wins-when-using-alpine-as-a-base-docker-image" rel="noopener noreferrer"&gt;&lt;em&gt;"The 3 Biggest Wins When Using Alpine as a Base Docker Image"&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Multi-stage builds&lt;/p&gt;

&lt;p&gt;Since there are many advantages to keeping Docker image sizes to a minimum, removing any unnecessary compile-time dependencies from Docker images will help cut down on the overall size. The best way to avoid including unnecessary files in Docker images is by using &lt;a href="https://docs.docker.com/develop/develop-images/multistage-build/" rel="noopener noreferrer"&gt;multi-stage builds&lt;/a&gt; in a &lt;code&gt;Dockerfile&lt;/code&gt;. Multi-stage builds allow "intermediate" images to be built where any necessary compile-time dependencies can be installed and then only the necessary files generated from these intermediate images can be copied into an optimized runtime image. Read &lt;a href="https://codesalad.dev/blog/smaller-docker-images-using-multi-stage-builds-8" rel="noopener noreferrer"&gt;this article&lt;/a&gt; by &lt;a href="https://twitter.com/GregorySchier" rel="noopener noreferrer"&gt;Greg Schier&lt;/a&gt; for a detailed explanation of how multi-stage builds work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;&lt;em&gt;"Dockerfile reference"&lt;/em&gt;&lt;/a&gt; in the Docker documentation which lists out all the possible instructions that can be used in a &lt;code&gt;Dockerfile&lt;/code&gt; and how to use them&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/" rel="noopener noreferrer"&gt;&lt;em&gt;"Best practices for writing Dockerfiles"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;&lt;a href="https://phoenixnap.com/kb/docker-cmd-vs-entrypoint" rel="noopener noreferrer"&gt;&lt;em&gt;"Docker CMD Vs Entrypoint Commands: What's The Difference?"&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://stackoverflow.com/a/24958548/8360496" rel="noopener noreferrer"&gt;Stack Overflow answer&lt;/a&gt; to &lt;em&gt;"What is the difference between the 'COPY' and 'ADD' commands in a Dockerfile?"&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker images
&lt;/h2&gt;

&lt;p&gt;Docker images contain the code and instructions used by Docker containers to know how to set up an application's environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building and tagging images
&lt;/h3&gt;

&lt;p&gt;Docker images are created using the &lt;code&gt;docker build&lt;/code&gt; command. When building Docker images, they are given a tag specified by the &lt;code&gt;--tag&lt;/code&gt; option. Tagging images is a way to give Docker images names/versions to know which image to pull from image repositories as well as to know which image should be used when running a container.&lt;/p&gt;

&lt;p&gt;Here's an example of building and tagging an image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--tag&lt;/span&gt; my-app:1.0 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking down the above command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker build&lt;/code&gt; specifies that a Docker image is being created&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--tag my-app:1:0&lt;/code&gt; specifies that the image should be assigned a repository name of &lt;code&gt;my-app&lt;/code&gt; and a tag of &lt;code&gt;1.0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.&lt;/code&gt; indicates that the Docker image should be built from a &lt;code&gt;Dockerfile&lt;/code&gt; that is found within the current directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;docker images&lt;/code&gt; command can be used to verify that the image has been created by listing out all the Docker images available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
my-app                 1.0                 964baf4833d3        8 minutes ago       322MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An image can also only have a repository name specified using the &lt;code&gt;--tag&lt;/code&gt; option, in which case a default tag of &lt;code&gt;latest&lt;/code&gt; will be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;--tag&lt;/span&gt; my-app &lt;span class="nb"&gt;.&lt;/span&gt;
docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
my-app                 latest              964baf4833d3        8 minutes ago       322MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to being able to tag images using the &lt;code&gt;--tag&lt;/code&gt; option with the &lt;code&gt;docker build&lt;/code&gt; command, Docker images can be tagged using the &lt;code&gt;docker tag&lt;/code&gt; command. Since the same image can have multiple tags, the &lt;code&gt;docker tag&lt;/code&gt; command allows for a new tag to be applied to an image that has already been tagged via the &lt;code&gt;docker build --tag&lt;/code&gt; command. To the &lt;code&gt;docker tag&lt;/code&gt; command can be avoided by correctly tagging an image using &lt;code&gt;docker build --tag&lt;/code&gt;, but if ever an image should have a different tag, that can be done using the &lt;code&gt;docker tag&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag my-app:1.0 robertcooper/my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will provide a repository name of &lt;code&gt;robertcooper/my-app&lt;/code&gt; and tag &lt;code&gt;1.0&lt;/code&gt; to the local image that has the name of &lt;code&gt;my-app&lt;/code&gt; and tag &lt;code&gt;1.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Listing out the images will yield the following results:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
robertcooper/my-app    1.0                 964baf4833d3        46 minutes ago      322MB
my-app                 1.0                 964baf4833d3        46 minutes ago      322MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how both images share the same image ID and only differ by the repository name. The repository name associated with an image is what determines to which Docker image registry/repository the image will be pushed when running the &lt;code&gt;docker push&lt;/code&gt; command. Docker image repositories and how to push and pull images is discussed in the &lt;em&gt;Image registries and pulling/pushing images&lt;/em&gt; section.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Beware of mutable Docker tag behavior&lt;/p&gt;

&lt;p&gt;Docker image tags are &lt;strong&gt;mutable&lt;/strong&gt;, which means that if an image is pushed to an image repository with a specific tag (e.g. 1.0.0), that tagged image can be overwritten with a different image that contains different code. This might be surprising for those that are more familiar with immutable dependency repositories like &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;. Mutable image tags have their benefits (such as making sure previously published versions of an image include security fixes), but this also means that a user might not be pulling the exact image they expect, which could result in non-deterministic deployments. To make sure the exact same image is pulled every time, an image's &lt;a href="https://docs.docker.com/engine/reference/commandline/images/#list-the-full-length-image-ids" rel="noopener noreferrer"&gt;digest&lt;/a&gt; can be specified, which is a "content-addressable identifier" that points to an image. If referencing images by their digest, instead of &lt;code&gt;docker pull node@8.10.0&lt;/code&gt;, the command would look like &lt;code&gt;docker pull node@sha256:06ebd9b1879057e24c1e87db508ba9fd0dd7f766bbf55665652d31487ca194eb&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://sysdig.com/blog/toctou-tag-mutability/" rel="noopener noreferrer"&gt;"Attack of the mutant tags! Or why tag mutability is a real security threat"&lt;/a&gt;&lt;/em&gt; explains the pros/cons of a mutable tag system in the context of Docker and how to reference image digests.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://renovate.whitesourcesoftware.com/blog/overcoming-dockers-mutable-image-tags/" rel="noopener noreferrer"&gt;"Overcoming Docker’s Mutable Image Tags"&lt;/a&gt;&lt;/em&gt; explains how to reference image digests and how &lt;a href="https://github.com/renovatebot/renovate" rel="noopener noreferrer"&gt;Renovate&lt;/a&gt; can be used to detect if a new image digest has been published for a specific image tag to alert users when there is an updated image available.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.freecodecamp.org/news/an-introduction-to-docker-tags-9b5395636c2a/" rel="noopener noreferrer"&gt;&lt;em&gt;"A quick introduction to Docker tags"&lt;/em&gt;&lt;/a&gt; by &lt;a href="https://twitter.com/ScribblingOn" rel="noopener noreferrer"&gt;Shubheksha Jalan&lt;/a&gt; gives a good explanation on how to tag images and what Docker tags represent&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/build/" rel="noopener noreferrer"&gt;&lt;code&gt;docker build&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/tag/" rel="noopener noreferrer"&gt;&lt;code&gt;docker tag&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Listing images
&lt;/h3&gt;

&lt;p&gt;Either use the &lt;code&gt;docker images&lt;/code&gt; (or &lt;code&gt;docker image ls&lt;/code&gt;) command to list out the Docker images available on the Docker host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
robertcooper/my-app    1.0                 964baf4833d3        46 minutes ago      322MB
my-app                 1.0                 964baf4833d3        46 minutes ago      322MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/images/" rel="noopener noreferrer"&gt;&lt;code&gt;docker images&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Image registries and pulling/pushing images
&lt;/h3&gt;

&lt;p&gt;Docker images are remotely saved in Docker &lt;strong&gt;image registries&lt;/strong&gt;, with the default Docker image registry being &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;. Docker image registries allow for Docker images to be stored and pulled down (i.e. downloaded) onto a Docker host to be used by a Docker container.&lt;/p&gt;

&lt;p&gt;To pull an image from Docker Hub, use the &lt;code&gt;docker pull&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull nginx:1.18.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will download the &lt;code&gt;nginx&lt;/code&gt; Docker image tagged &lt;code&gt;1.18.0&lt;/code&gt; from Docker Hub. After running the &lt;code&gt;docker pull&lt;/code&gt; command, the image should show up when listing out the images using &lt;code&gt;docker images&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
nginx                  1.18.0              20ade3ba43bf        6 days ago          133MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the tag is not explicitly specified when pulled, the image tagged with &lt;code&gt;latest&lt;/code&gt; will be pulled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPOSITORY             TAG                 IMAGE ID            CREATED             SIZE
nginx                  latest              992e3b7be046        6 days ago          133MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example uses the &lt;a href="https://hub.docker.com/_/nginx" rel="noopener noreferrer"&gt;nginx image&lt;/a&gt;, which is an official Docker Hub image. Official Docker Hub images are images that are formally approved by Docker Hub and the images are regularly tested for security vulnerabilities. Read more about official Docker images &lt;a href="https://docs.docker.com/docker-hub/official_images/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anyone can create their own account and repository on Docker Hub and push images to the repository. Pushing images to Docker Hub means that the images are saved at Docker Hub in the repository specified using the &lt;code&gt;docker push&lt;/code&gt; command. The &lt;code&gt;docker push&lt;/code&gt; command takes the form of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push &amp;lt;hub-user&amp;gt;/&amp;lt;repo-name&amp;gt;:&amp;lt;tag&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example usage of this would look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push robertcooper/my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, this pushes a local image with a repository name of &lt;code&gt;robertcooper/my-app&lt;/code&gt; and tag of &lt;code&gt;1.0&lt;/code&gt; to Docker Hub.&lt;/p&gt;

&lt;p&gt;To have the rights to push an image to an image registry, a user must first log in using &lt;code&gt;docker login&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login &lt;span class="nt"&gt;--username&lt;/span&gt; robertcooper
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will attempt to authenticate to the &lt;code&gt;robertcooper&lt;/code&gt; Docker Hub account. Executing the command will prompt a user for the password, and if successful, it will now be possible to push to Docker Hub repositories associated with the &lt;code&gt;robertcooper&lt;/code&gt; Docker Hub account. Login with &lt;code&gt;docker login&lt;/code&gt; is also required to pull images from private repositories.&lt;/p&gt;

&lt;p&gt;Docker Hub is not the only image registry available for users to use, there are also other popular image registry offerings such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/ecr/" rel="noopener noreferrer"&gt;Amazon ECR&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/container-registry" rel="noopener noreferrer"&gt;Google Cloud Container Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.microsoft.com/en-us/services/container-registry/" rel="noopener noreferrer"&gt;Azure Container Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/free-pro-team@latest/packages/getting-started-with-github-container-registry/about-github-container-registry" rel="noopener noreferrer"&gt;GitHub Container Registry&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each Docker registry has its own pricing. Docker Hub allows for unlimited public repositories and 1 private repository on their free plan, but for more private repositories an upgrade to their Pro plan is required, which is $60 a year or $7 a month. Amazon ECR, on the other hand, charges $0.10 per GB/month for the storage space that the images take and additionally charges between $0.05 and $0.09 per GB of images that are pulled (i.e. data transfer &lt;strong&gt;out&lt;/strong&gt; is charged, but data transfer &lt;strong&gt;in&lt;/strong&gt; is free).&lt;/p&gt;

&lt;p&gt;If pulling images from a repository that is not on Docker Hub, the repository name in the &lt;code&gt;docker push&lt;/code&gt; and &lt;code&gt;docker pull&lt;/code&gt; commands will need to be prefixed by the hostname corresponding to an image repository. &lt;code&gt;docker push&lt;/code&gt; and &lt;code&gt;docker pull&lt;/code&gt; commands that don't specify a hostname will default to Docker Hub as the image registry. For example, if pulling an image hosted on Amazon ECR, it might look similar to the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull 183746294028.dkr.ecr.us-east-1.amazonaws.com/robertcooper/my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above example, &lt;code&gt;183746294028.dkr.ecr.us-east-1.amazonaws.com&lt;/code&gt; is the hostname for the image repository, &lt;code&gt;robertcooper/my-app&lt;/code&gt; is the name of the repository, and &lt;code&gt;1.0&lt;/code&gt; is the tag.&lt;/p&gt;

&lt;p&gt;Remember that authentication using &lt;code&gt;docker login&lt;/code&gt; is required to push images, no matter which registry is used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/docker-hub/" rel="noopener noreferrer"&gt;&lt;em&gt;"Docker Hub Quickstart"&lt;/em&gt;&lt;/a&gt; in the Docker documentation on how to create an image repository on Docker Hub&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/pull/" rel="noopener noreferrer"&gt;&lt;code&gt;docker pull&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/push/" rel="noopener noreferrer"&gt;&lt;code&gt;docker push&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/login/" rel="noopener noreferrer"&gt;&lt;code&gt;docker login&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Removing images
&lt;/h3&gt;

&lt;p&gt;To remove a docker image use the &lt;code&gt;docker rmi&lt;/code&gt; or &lt;code&gt;docker image rm&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Images that are already being used by containers will need to have the containers removed before attempting to remove the image or the &lt;code&gt;--force&lt;/code&gt; option can be passed to the &lt;code&gt;docker rmi&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi &lt;span class="nt"&gt;--force&lt;/span&gt; my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are two useful commands to clear out all images at once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;# remove all images&lt;/span&gt;
docker rmi &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="c"&gt;# same as above, but forces the images associated with running containers to also be removed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/rmi/" rel="noopener noreferrer"&gt;&lt;code&gt;docker rmi&lt;/code&gt;&lt;/a&gt; command in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Saving and loading images
&lt;/h3&gt;

&lt;p&gt;There may be situations where saving a Docker image to a file and then loading the image onto a Docker host via the file could be useful. For example, a CI check that builds a Docker image might use that same image in another CI check. Instead of pushing the image to an image repository and pulling it down for use in another CI check, it may be beneficial to save the image to a file in a persistent storage on the CI server and then load the image from the other CI check that should use the same built image.&lt;/p&gt;

&lt;p&gt;To save a Docker image, use the &lt;code&gt;docker save&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker save &lt;span class="nt"&gt;--output&lt;/span&gt; my-app.tar my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will save the Docker image &lt;code&gt;my-app:1.0&lt;/code&gt; to a &lt;a href="https://en.wikipedia.org/wiki/Tar_(computing)" rel="noopener noreferrer"&gt;tarball&lt;/a&gt; file named &lt;code&gt;my-app.tar&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The newly saved tarball file can be loaded into a Docker host as a Docker image using the &lt;code&gt;docker load&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker load &lt;span class="nt"&gt;--input&lt;/span&gt; my-app.tar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Loaded image: my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/save/" rel="noopener noreferrer"&gt;&lt;code&gt;docker save&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/load/" rel="noopener noreferrer"&gt;&lt;code&gt;docker load&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker containers
&lt;/h2&gt;

&lt;p&gt;Docker containers are isolated environments used to run applications. Docker containers are described by their corresponding Docker images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running containers
&lt;/h3&gt;

&lt;p&gt;Docker containers are created by running an environment specified by a Docker image. Docker containers are started using the &lt;code&gt;docker run&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will create a container using the &lt;code&gt;my-app:1.0&lt;/code&gt; image. Executing the &lt;code&gt;docker run&lt;/code&gt; command will boot up the container and also execute the command specified by the &lt;a href="https://docs.docker.com/engine/reference/builder/#cmd" rel="noopener noreferrer"&gt;&lt;code&gt;CMD&lt;/code&gt; instruction&lt;/a&gt; that was specified in the image's &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To verify that the docker container is running, execute &lt;code&gt;docker ps&lt;/code&gt; to list out the running containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                               NAMES
ec488b832e0a        my-app:1.0             "docker-entrypoint.s…"   13 minutes ago      Up 13 minutes                                           practical_buck
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the output of the above command shows there is one container running with a container ID of &lt;code&gt;ec488b832e0a&lt;/code&gt; and the name of &lt;code&gt;practical_buck&lt;/code&gt;. Both the container ID and container name are randomly generated and can be used for other Docker CLI commands that require the container name/ID to be identified. It's also possible to assign a more appropriate and rememberable name for a container by passing a value to the &lt;code&gt;--name&lt;/code&gt; option of the &lt;code&gt;docker run&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; my-app my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the name of &lt;code&gt;my-app&lt;/code&gt; is assigned to the running docker container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONTAINER ID        IMAGE                  COMMAND                  CREATED             STATUS              PORTS                               NAMES
6cf7fd48703e        my-app:1.0             "docker-entrypoint.s…"   13 minutes ago      Up 13 minutes                                           my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/run/" rel="noopener noreferrer"&gt;&lt;code&gt;docker run&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/ps/" rel="noopener noreferrer"&gt;&lt;code&gt;docker ps&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Detached mode and viewing logs
&lt;/h3&gt;

&lt;p&gt;By default, running a docker container using &lt;code&gt;docker run&lt;/code&gt; will attach the container's process output to the console in which the &lt;code&gt;docker run&lt;/code&gt; command was executed. This means all the logs for the container appear in the console in real-time. However, it's also possible to run a container in &lt;em&gt;detached mode&lt;/em&gt; by using the &lt;code&gt;-d&lt;/code&gt; option, which would allow the console to be free to execute further commands while the docker container is running.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; my-app:1.0  &lt;span class="c"&gt;# Runs a docker container in detached mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a container is running in detached mode, the logs can be viewed using the &lt;code&gt;docker logs&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs ec488b832e0a 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command gets the logs for a container with an ID of &lt;code&gt;ec488b832e0a&lt;/code&gt;. The container's name could also be used for the &lt;code&gt;docker logs&lt;/code&gt; command to get the same result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker logs my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/logs/" rel="noopener noreferrer"&gt;&lt;code&gt;docker logs&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exposing ports
&lt;/h3&gt;

&lt;p&gt;If a running container exposes a port (e.g. port 3000), then a mapping of ports between the Docker host and the Docker container is required to access the application outside of Docker (e.g. to view a web app running in Docker in a Chrome browser at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will run a container that will be accessible at &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; on the host. Visiting &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; in the browser should display the running app (assuming the app is a web application).&lt;/p&gt;

&lt;p&gt;Often the port numbers between the Docker host and Docker container end up being the same value, but it's also possible to map to a different port on the host machine, which can be desirable if a port on the host is already occupied.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:3000 my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will run a container accessible at &lt;a href="http://localhost:8000" rel="noopener noreferrer"&gt;http://localhost:8000&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stopping and removing containers
&lt;/h3&gt;

&lt;p&gt;To stop running a docker container, use the &lt;code&gt;docker stop&lt;/code&gt; (or &lt;code&gt;docker container stop&lt;/code&gt;) command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;docker stop&lt;/code&gt; will send a &lt;code&gt;SIGTERM&lt;/code&gt; signal in the container to try and gracefully terminate the running process. If after 10 seconds the container doesn't stop, a &lt;code&gt;SIGKILL&lt;/code&gt; signal will be sent, which does a more forceful termination of the running process.&lt;/p&gt;

&lt;p&gt;There is also the &lt;code&gt;docker kill&lt;/code&gt; (or &lt;code&gt;docker container kill&lt;/code&gt;) command which will immediately send a &lt;code&gt;SIGKILL&lt;/code&gt; signal to the container for a forceful termination of the container's process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;kill &lt;/span&gt;my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is possible to restart a stopped container using the &lt;code&gt;docker start&lt;/code&gt; (or &lt;code&gt;docker container start&lt;/code&gt;) command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker start my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To remove containers no longer in use, use the &lt;code&gt;docker rm&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm &lt;/span&gt;my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the &lt;code&gt;docker rm&lt;/code&gt; command will only permit &lt;strong&gt;stopped&lt;/strong&gt; containers from being removed. To remove containers that are running, use the &lt;code&gt;-f&lt;/code&gt; (&lt;code&gt;--force&lt;/code&gt;) option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;code&gt;-f&lt;/code&gt; option will send a &lt;code&gt;SIGKILL&lt;/code&gt; signal to the running container to stop it and then the container will be removed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/stop/" rel="noopener noreferrer"&gt;&lt;code&gt;docker stop&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/kill/" rel="noopener noreferrer"&gt;&lt;code&gt;docker kill&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/start/" rel="noopener noreferrer"&gt;&lt;code&gt;docker start&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/rm/" rel="noopener noreferrer"&gt;&lt;code&gt;docker rm&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Listing containers
&lt;/h3&gt;

&lt;p&gt;To view a list of running containers, use the &lt;code&gt;docker ps&lt;/code&gt; (or &lt;code&gt;docker container ls&lt;/code&gt;) command. By default, the containers shown with &lt;code&gt;docker ps&lt;/code&gt; are the containers that are running. To include stopped containers, pass the &lt;code&gt;-a&lt;/code&gt; (&lt;code&gt;--all&lt;/code&gt;) option to the command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt;  &lt;span class="c"&gt;# includes stopped containers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/engine/reference/commandline/ps/" rel="noopener noreferrer"&gt;&lt;code&gt;docker ps&lt;/code&gt; command&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Execute commands in a running container
&lt;/h3&gt;

&lt;p&gt;To run a command inside a running container, use the &lt;code&gt;docker exec&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec &lt;/span&gt;my-app &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dockerfile
README.md
node_modules
package.json
pages
public
styles
yarn.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful command to exec is one that allows connecting to the container's shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; my-app sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running the above command will connect the command line to the Docker container's shell where it will be possible to execute further commands, such as &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;echo&lt;/code&gt;, etc. The &lt;code&gt;-it&lt;/code&gt; option is required to have the command line shell be connected to the Docker container's shell. For more details on what the &lt;code&gt;-it&lt;/code&gt; command does, &lt;a href="https://devconnected.com/docker-exec-command-with-examples/" rel="noopener noreferrer"&gt;read this article&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; bash != sh&lt;/p&gt;

&lt;p&gt;In the above command, &lt;code&gt;sh&lt;/code&gt; is used instead of &lt;code&gt;bash&lt;/code&gt; since &lt;code&gt;bash&lt;/code&gt; might not be installed on the Docker image. For example, Alpine Linux Docker images don't have &lt;code&gt;bash&lt;/code&gt; installed on them by default, so &lt;code&gt;bash&lt;/code&gt; would either need to be installed via an instruction in the &lt;code&gt;Dockerfile&lt;/code&gt; (see &lt;a href="https://stackoverflow.com/a/40944512/8360496" rel="noopener noreferrer"&gt;this Stack Overflow answer to do so&lt;/a&gt;) or &lt;code&gt;sh&lt;/code&gt; could be used since it comes installed on Alpine Linux. &lt;code&gt;sh&lt;/code&gt; should be available on most/all Linux distributions, whereas &lt;code&gt;bash&lt;/code&gt; might not be natively installed. &lt;code&gt;bash&lt;/code&gt; is a superset of &lt;code&gt;sh&lt;/code&gt; (in the same way that TypeScript is a superset of JavaScript), which means that &lt;code&gt;bash&lt;/code&gt; has some additional functionality over &lt;code&gt;sh&lt;/code&gt;, but for typical usage in the context of &lt;code&gt;docker exec -it my-app sh&lt;/code&gt;, there shouldn't be a need for the extra features provided by &lt;code&gt;bash&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For more details &lt;a href="https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash" rel="noopener noreferrer"&gt;read this great resource on Stack Overflow&lt;/a&gt; which answers the question: &lt;em&gt;"Difference between sh and bash"&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;docker run&lt;/code&gt; command can also be used to run a command in a Docker container. The difference between &lt;code&gt;docker run&lt;/code&gt; and &lt;code&gt;docker exec&lt;/code&gt; is that &lt;code&gt;docker exec&lt;/code&gt; needs to be used on a container that is &lt;strong&gt;already running&lt;/strong&gt;, whereas the &lt;code&gt;docker run&lt;/code&gt; command will &lt;strong&gt;create a new container&lt;/strong&gt; to run the specified command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run my-app:1.0 &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will start a container with the &lt;code&gt;my-app:1.0&lt;/code&gt; image and execute the &lt;code&gt;ls&lt;/code&gt; command. Listing out the Docker containers (&lt;code&gt;docker ps --all&lt;/code&gt;) before and after executing a &lt;code&gt;docker run&lt;/code&gt; command will show that a new container was created.&lt;/p&gt;

&lt;p&gt;Remember that the &lt;code&gt;docker run&lt;/code&gt; command, as explained at the beginning of the section on Docker containers, is also used to create a Docker container and will run any commands that are specified in the container's associated image. This is probably how the &lt;code&gt;docker run&lt;/code&gt; command is most often used, however, it can also be used to run one-off commands as explained in the aforementioned paragraphs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://devconnected.com/docker-exec-command-with-examples/" rel="noopener noreferrer"&gt;&lt;em&gt;"Docker Exec Command With Examples"&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/exec/" rel="noopener noreferrer"&gt;&lt;code&gt;docker exec&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/run/" rel="noopener noreferrer"&gt;&lt;code&gt;docker run&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Get details of a container
&lt;/h3&gt;

&lt;p&gt;To get details about a docker container, the &lt;code&gt;docker inspect&lt;/code&gt; command can be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is quite long for the &lt;code&gt;docker inspect&lt;/code&gt; command since it includes a ton of information related to the Docker container, such as its full ID, when the container was created, the command the container ran when it started, the network settings, and a whole lot more.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;docker inspect&lt;/code&gt; command is not exclusive to Docker containers, but can be used for other Docker objects such as Docker images.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect my-app:1.0  &lt;span class="c"&gt;# inspect a Docker image&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To get live data on the resource consumption usage of a Docker container, such as CPU, memory, and I/O, use the &lt;code&gt;docker stats&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stats my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
4eef7af61c6f        my-app              0.03%               46.73MiB / 1.944GiB   2.35%               906B / 0B           0B / 0B             18
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; Resource limits on the Docker host&lt;/p&gt;

&lt;p&gt;The total CPU and Memory used to calculate the &lt;code&gt;CPU %&lt;/code&gt; and &lt;code&gt;MEM %&lt;/code&gt; values don't necessarily correspond with the total CPU and memory available on the physical machine since the Docker host can be configured to have a fraction of the CPUs/RAM available on the machine. CPU, memory, and disk space limits can be easily configured with Docker Desktop to make sure that the Docker host doesn't have access to too many resources on the machine.&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%2Fbsalor0cwhtjmeaxj570.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%2Fbsalor0cwhtjmeaxj570.png" alt="Docker Desktop configuration of resources such as CPU, memory, and disk space"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Docker Desktop configuration of resource limits on the Docker host.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/inspect/" rel="noopener noreferrer"&gt;&lt;code&gt;docker inspect&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/commandline/stats/" rel="noopener noreferrer"&gt;&lt;code&gt;docker stats&lt;/code&gt;&lt;/a&gt; command in the documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker volumes
&lt;/h2&gt;

&lt;p&gt;Docker volumes are used to persist data in Docker containers. That means that a container can be stopped and restarted and the application's data/state can be maintained. Docker volumes can also allow multiple different containers to share data by having all the containers point to the same volume.&lt;/p&gt;

&lt;p&gt;Docker volumes are saved in the Docker storage directory on the host filesystem. The Docker storage directory is &lt;code&gt;/var/lib/docker/volumes&lt;/code&gt; on Linux, but it shouldn't matter to the user where Docker saves these volumes since users will be relying on the Docker CLI to interact with volumes.&lt;/p&gt;

&lt;p&gt;A volume can be mounted to a container by passing the &lt;code&gt;-v&lt;/code&gt; (&lt;code&gt;--volume&lt;/code&gt;) option to the &lt;code&gt;docker run&lt;/code&gt; command when starting a container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app &lt;span class="nt"&gt;-v&lt;/span&gt; my-volume:/usr/src/app my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will map a volume named &lt;code&gt;my-volume&lt;/code&gt; to the code found in the &lt;code&gt;/usr/src/app&lt;/code&gt; directory in the Docker container.&lt;/p&gt;

&lt;p&gt;List out all the available Docker volumes using &lt;code&gt;docker volume ls&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DRIVER              VOLUME NAME
local               my-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Volumes can also be created using the &lt;code&gt;docker volume create&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker volume create my-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There shouldn't be many use cases where the &lt;code&gt;docker volume create&lt;/code&gt; command is necessary since volumes are likely to be created/specified with the &lt;code&gt;docker run -v&lt;/code&gt; command or with Docker Compose.&lt;/p&gt;

&lt;p&gt;A volume name doesn't need to be explicitly passed when creating a volume as Docker will generate a random name for the volume.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app &lt;span class="nt"&gt;-v&lt;/span&gt; /usr/src/app my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To find out the name that was assigned to the Docker volume created by the above command, run the &lt;code&gt;docker inspect&lt;/code&gt; command to get details on the container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output will contain a section called "Mounts" with the information about the volume.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
  "Mounts": [
    {
        "Type": "volume",
        "Name": "7ce1df6e218cda9c64917c51c1035e7291791043f9722db2fe38156cb9dc98f3",
        "Source": "/var/lib/docker/volumes/7ce1df6e218cda9c64917c51c1035e7291791043f9722db2fe38156cb9dc98f3/_data",
        "Destination": "/usr/src/app",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
  ],
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above output, &lt;code&gt;7ce1df6e218cda9c64917c51c1035e7291791043f9722db2fe38156cb9dc98f3&lt;/code&gt; is the name of the volume.&lt;/p&gt;

&lt;p&gt;Usually, the name of the volume should be explicitly defined to make sure the same volume is used every time a container is started.&lt;/p&gt;

&lt;p&gt;Docker also provides the option to use what are called &lt;a href="https://docs.docker.com/storage/bind-mounts/" rel="noopener noreferrer"&gt;&lt;em&gt;bind mounts&lt;/em&gt;&lt;/a&gt;, which behave very similarly to Docker volumes. A bind mount is a directory found on the host machine that will be mounted into a Docker container. The main difference between a bind mount and a Docker volume is that Docker volumes are managed by the Docker engine, so the &lt;code&gt;docker volume&lt;/code&gt; command can be used to interact with the volumes, and the volumes are all saved within Docker's storage directory.&lt;/p&gt;

&lt;p&gt;As an example, a directory on a user's desktop could be used as the bind mount for a container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app &lt;span class="nt"&gt;-v&lt;/span&gt; ~/Desktop/my-app:/usr/src/app my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bind mounts won't show up when running the &lt;code&gt;docker volume ls&lt;/code&gt; command since bind mounts are not "managed" by Docker.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pro tip:&lt;/strong&gt; Live reloading&lt;/p&gt;

&lt;p&gt;Docker volumes can be leveraged to get live reloading capabilities when developing applications with Docker. &lt;a href="https://www.freecodecamp.org/news/how-to-enable-live-reload-on-docker-based-applications/" rel="noopener noreferrer"&gt;This Free Code Camp tutorial&lt;/a&gt; explains how to set up a Docker app to allow for live reloading of a Node.js application that is written in TypeScript. The tutorial explains how a Docker volume is used to mirror files between a local file system and a Docker container. The tutorial also explains how to override the default command specified in a Dockerfile via the Docker CLI to have the Docker container run a watcher process that watches for TypeScript files to be changed to transpile them into JavaScript, which will, in turn, trigger the application to live reload.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/storage/" rel="noopener noreferrer"&gt;&lt;em&gt;"Manage data in Docker"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/storage/bind-mounts/" rel="noopener noreferrer"&gt;&lt;em&gt;"Use bind mounts"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=p2PH_YPCsis&amp;amp;ab_channel=TechWorldwithNana" rel="noopener noreferrer"&gt;YouTube: &lt;em&gt;"Docker Volumes explained in 6 minutes"&lt;/em&gt;&lt;/a&gt; by &lt;a href="https://www.youtube.com/channel/UCdngmbVKX1Tgre699-XLlUA" rel="noopener noreferrer"&gt;TechWorld with Nana&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=VOK06Q4QqvE&amp;amp;ab_channel=AutomationStepbyStep-RaghavPal" rel="noopener noreferrer"&gt;YouTube: &lt;em&gt;"What is Docker Volume | How to create Volumes | What is Bind Mount | Docker Storage"&lt;/em&gt;&lt;/a&gt; by &lt;a href="https://www.youtube.com/channel/UCTt7pyY-o0eltq14glaG5dg" rel="noopener noreferrer"&gt;Raghav Pal&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker networks
&lt;/h2&gt;

&lt;p&gt;Docker networks are used to allow containers to be well isolated from one another and they are also used if containers need to be able to communicate with each other.&lt;/p&gt;

&lt;p&gt;Docker networks have different drivers that allow for different kinds of networks. The default driver is called a "bridge" driver and when starting a container without specifying a specific network, the container will be running on a bridge network that is named "bridge". However, Docker recommends a user-defined bridge network be used if different containers need to communicate with one another.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running a container using the above command would connect the container to the default bridge network. This can be verified by using the &lt;code&gt;docker inspect&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
"NetworkSettings": {
    "Bridge": "",
    "SandboxID": "33bf53f6badba3f19e4bcdb18e55d198a48672f23187be8934e20f31e6aad18f",
    "HairpinMode": false,
    "LinkLocalIPv6Address": "",
    "LinkLocalIPv6PrefixLen": 0,
    "Ports": {},
    "SandboxKey": "/var/run/docker/netns/33bf53f6badb",
    "SecondaryIPAddresses": null,
    "SecondaryIPv6Addresses": null,
    "EndpointID": "",
    "Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "IPAddress": "",
    "IPPrefixLen": 0,
    "IPv6Gateway": "",
    "MacAddress": "",
    "Networks": {
        "bridge": {
            "IPAMConfig": null,
            "Links": null,
            "Aliases": null,
            "NetworkID": "94c91e903283f9686d2d6f16bb10e28e95b004d81f81415d04f0cf710af006f9",
            "EndpointID": "",
            "Gateway": "",
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "MacAddress": "",
            "DriverOpts": null
        }
    }
}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To create a user-defined network, use the &lt;code&gt;docker network create&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create my-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connect to the user-defined network by using the &lt;code&gt;--network&lt;/code&gt; option with &lt;code&gt;docker run&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app &lt;span class="nt"&gt;--network&lt;/span&gt; my-network my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opt to connect a network to a running container using &lt;code&gt;docker network connect&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network connect my-network my-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, only the bridge network driver has been mentioned since that is all that most people need when working with Docker. However, there are 3 other network drivers that come with Docker and can be used for container networking:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;host&lt;/strong&gt;: The host driver is the network that the Docker host uses. It may be desirable to have a container using the Docker's host network if the number of available ports while using bridge networks are too limited.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;none&lt;/strong&gt;: Containers that don't need to be connected to a network can use no network. This means that input and output would be done through &lt;code&gt;STDIN&lt;/code&gt; and &lt;code&gt;STDOUT&lt;/code&gt; or through files mirrored in a Docker volume.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;overlay&lt;/strong&gt;: Used to connect Docker containers that are on different Docker hosts. This is most often used when running Docker in &lt;a href="https://docs.docker.com/engine/swarm/swarm-mode/" rel="noopener noreferrer"&gt;swarm mode&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;maclan&lt;/strong&gt;: Used to assign a MAC address to a container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view the list of Docker networks on the Docker host, run the &lt;code&gt;docker network ls&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NETWORK ID          NAME                         DRIVER              SCOPE
e538e11182fd        my-network                   bridge              local
409d0b996c9d        bridge                       bridge              local
39a73b1d3dc1        host                         host                local
8616053c1b28        none                         null                local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above output shows that there are 4 networks on the current Docker host:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The user-defined bridge network named "my-network"&lt;/li&gt;
&lt;li&gt;The default bridge network named "bridge"&lt;/li&gt;
&lt;li&gt;The host network named "host"&lt;/li&gt;
&lt;li&gt;The network named "none" which is used for containers that should not be connected to a network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/network/" rel="noopener noreferrer"&gt;&lt;em&gt;"Networking overview"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/network/bridge/" rel="noopener noreferrer"&gt;&lt;em&gt;"Use bridge networks"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Removing unused images, containers, and volumes
&lt;/h2&gt;

&lt;p&gt;A computer's hard drive can quickly become bloated with old and unused Docker objects (i.e. images, containers, and volumes) that accumulate as a user works with Docker.&lt;/p&gt;

&lt;p&gt;Here's a list of some of the useful commands to clear out old images, containers, and volumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker system prune  &lt;span class="c"&gt;# cleans images, containers, volumes, and networks that are not associated with a container&lt;/span&gt;
docker system prune &lt;span class="nt"&gt;-a&lt;/span&gt;  &lt;span class="c"&gt;# same as above, but includes stopped containers and unused images&lt;/span&gt;

docker volume prune  &lt;span class="c"&gt;# removes volumes that are not connected to containers (aka "dangling" volumes)&lt;/span&gt;

docker rmi &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;# removes all images that are not associated with existing containers&lt;/span&gt;
docker image prune &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="c"&gt;# same as the above command&lt;/span&gt;
docker rmi &lt;span class="si"&gt;$(&lt;/span&gt;docker images &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="c"&gt;# same as above, but forces the images associated with existing containers (running or stopped) to also be removed&lt;/span&gt;

docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;# removes all containers&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;docker ps &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt;  &lt;span class="c"&gt;# same as above, but forces running containers to also be removed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes" rel="noopener noreferrer"&gt;&lt;em&gt;How To Remove Docker Images, Containers, and Volumes&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Docker Compose
&lt;/h2&gt;

&lt;p&gt;Docker Compose is a tool that simplifies the communication with the Docker engine. Every interaction with the Docker engine can be done via the regular Docker CLI, but Docker Compose allows for the definition of containers to be done in &lt;code&gt;docker-compose.yml&lt;/code&gt; files with the use of the &lt;code&gt;docker-compose&lt;/code&gt; CLI commands to interact with the Docker engine. This allows you to container configuration details away from the regular &lt;code&gt;docker&lt;/code&gt; CLI commands and into Docker Compose files.&lt;/p&gt;

&lt;p&gt;Before being able to run any commands with &lt;code&gt;docker-compose&lt;/code&gt;, it is required to specify the &lt;em&gt;services&lt;/em&gt; in a &lt;code&gt;docker-compose.yml&lt;/code&gt; file. A service describes what image should be used for a running container and any other configuration associated with a container, such as environment variables, ports to be exposed, volumes to be used, etc.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; Why "service"?&lt;/p&gt;

&lt;p&gt;As mentioned, the blocks that describe Docker containers in the &lt;code&gt;docker-compose.yml&lt;/code&gt; file are called &lt;strong&gt;services&lt;/strong&gt;. The term "service" is often used to refer to the parts that make up some larger application. The whole &lt;a href="https://medium.com/hashmapinc/the-what-why-and-how-of-a-microservices-architecture-4179579423a9" rel="noopener noreferrer"&gt;microservices architecture&lt;/a&gt; is based on this idea.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's an example &lt;code&gt;docker-compose.yml&lt;/code&gt; file that describes three services: a web-app, an API, and a database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "3.8"
services:
  web-app:
    container_name: web-app
    build: ./web-app
    ports:
      - "3000:80"
  api:
    container_name: api
    build: ./api
    ports:
      - "5000:5000"
  db:
    container_name: db
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: password
    volumes:
      - db-volume:/var/lib/postgresql/data
volumes:
  db-volume:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking down the above &lt;code&gt;docker-compose.yml&lt;/code&gt;, we can see that we are first defining the version of Docker Compose that should be used (&lt;code&gt;3.8&lt;/code&gt; being the latest version at the time of this writing).&lt;/p&gt;

&lt;p&gt;Next, there are 3 services that are described: &lt;code&gt;web-app&lt;/code&gt;, &lt;code&gt;api&lt;/code&gt;, and &lt;code&gt;db&lt;/code&gt;. Each service has a &lt;code&gt;container_name&lt;/code&gt; defined, which will correspond with the name of the Docker container when running the services with Docker Compose. To start a service, the &lt;code&gt;docker-compose up&lt;/code&gt; command can be used. If specifying the name of a service, it will start that specific service. If no service is specified, all services will be started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up api  &lt;span class="c"&gt;# Will only start the api service&lt;/span&gt;
docker-compose up  &lt;span class="c"&gt;# Will start all the services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The services can be run in detached mode to keep control of the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up api &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's possible to verify the containers are running using the &lt;code&gt;docker ps&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS  
            PORTS                    NAMES
4c33deed7688        my-app_web-app      "/docker-entrypoint.…"   3 days ago          Up 7 hours          0.0.0.0:3000-&amp;gt;80/tcp     web-app
7c3fc92ad1c4        my-app_api          "docker-entrypoint.s…"   4 days ago          Up 7 hours          0.0.0.0:5000-&amp;gt;5000/tcp   api
acc4dcd27a2b        postgres            "docker-entrypoint.s…"   4 days ago          Up 7 hours          0.0.0.0:5432-&amp;gt;5432/tcp   db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;web-app&lt;/code&gt; and &lt;code&gt;api&lt;/code&gt; services have a &lt;code&gt;build&lt;/code&gt; option which is pointing to the location of the &lt;code&gt;Dockerfile&lt;/code&gt; that corresponds with each service. The location of the &lt;code&gt;Dockerfile&lt;/code&gt; is required for Docker Compose to know how to build images associated with those services.&lt;/p&gt;

&lt;p&gt;To build the images with Docker Compose, use the &lt;code&gt;docker-compose build&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose build api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above command will build an image for the &lt;code&gt;api&lt;/code&gt; service with a default name following the format of &lt;code&gt;[folder name]_[service name]&lt;/code&gt;. So if the folder in which the &lt;code&gt;docker-compose.yml&lt;/code&gt; file is found is named &lt;code&gt;my-app&lt;/code&gt;, then the build image will be named &lt;code&gt;my-app_api&lt;/code&gt;. The image will also be given a tag of &lt;code&gt;latest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Building images with &lt;code&gt;docker-compose build&lt;/code&gt; should not be necessary for most situations since running the &lt;code&gt;docker-compose up&lt;/code&gt; command will automatically build any missing images. However, it may be desirable to re-build an image if the image tagged as &lt;code&gt;latest&lt;/code&gt; is old and needs to be updated with new code.&lt;/p&gt;

&lt;p&gt;Notice that in the above &lt;code&gt;docker-compose.yml&lt;/code&gt; file, the &lt;code&gt;db&lt;/code&gt; service doesn't have a &lt;code&gt;build&lt;/code&gt; option. That's because the database service is using the official PostgreSQL image from Docker Hub, so there is no need to build an image.&lt;/p&gt;

&lt;p&gt;Each service has the ports it would like to expose to the Docker host using the &lt;code&gt;ports&lt;/code&gt; option, where the first port number is the port on the Docker host and the second number is the port in the Docker container. Taking the web app as an example, we are mapping the Docker host port 3000 to port 80 of the Docker container since the web app service runs an NGINX server that serves HTML to port 80.&lt;/p&gt;

&lt;p&gt;Also, notice an environment variable is being set for the &lt;code&gt;db&lt;/code&gt; service. The &lt;code&gt;POSTGRES_PASSWORD&lt;/code&gt; environment variable is being set to a value of "password" (mandatory disclaimer that using "password" for your password is not secure). Environment variables specified using the &lt;code&gt;environment&lt;/code&gt; option in Docker Compose makes the environment variables available in the associated Docker container, but &lt;strong&gt;not&lt;/strong&gt; during build time. Therefore environment variables are not accessible in the &lt;code&gt;Dockerfile&lt;/code&gt;. To have variables accessible at build time in the &lt;code&gt;Dockerfile&lt;/code&gt;, use the &lt;a href="https://docs.docker.com/compose/compose-file/#args" rel="noopener noreferrer"&gt;&lt;code&gt;args&lt;/code&gt; sub-option&lt;/a&gt; for the &lt;a href="https://docs.docker.com/compose/compose-file/#build" rel="noopener noreferrer"&gt;&lt;code&gt;build&lt;/code&gt; option&lt;/a&gt; in the &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;db&lt;/code&gt; service also makes use of a named volume. The named volume of &lt;code&gt;db-volume&lt;/code&gt; is specified at the bottom of the &lt;code&gt;docker-compose.yml&lt;/code&gt; file and the mapping of the volume to the directory in the Docker container is done with the &lt;code&gt;volumes&lt;/code&gt; option on the &lt;code&gt;db&lt;/code&gt; service. Notice that the &lt;code&gt;docker-compose.yml&lt;/code&gt; file is mapping the &lt;code&gt;db-volume&lt;/code&gt; volume to the &lt;code&gt;/var/lib/postgresql/data&lt;/code&gt; directory in the Docker container which allows for the database data to be persisted when restarting the &lt;code&gt;db&lt;/code&gt; service.&lt;/p&gt;

&lt;p&gt;Here's a list of frequently used Docker Compose options in the &lt;code&gt;docker-compose.yml&lt;/code&gt; file:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#build" rel="noopener noreferrer"&gt;&lt;code&gt;build&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Configuration on how to build an image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#args" rel="noopener noreferrer"&gt;&lt;code&gt;build.args&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Used to specify build-time variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#command" rel="noopener noreferrer"&gt;&lt;code&gt;command&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Overrides the default CMD defined by an image's &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#container_name" rel="noopener noreferrer"&gt;&lt;code&gt;container_name&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;The name that should be used for the service's container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#depends_on" rel="noopener noreferrer"&gt;&lt;code&gt;depends_on&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Used to determine the order in which containers should be started&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#entrypoint" rel="noopener noreferrer"&gt;&lt;code&gt;env_file&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Adds environment variables from a file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#environment" rel="noopener noreferrer"&gt;&lt;code&gt;environment&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Specify environment variables&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#image" rel="noopener noreferrer"&gt;&lt;code&gt;image&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Specifies the image to be used by the container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#networks" rel="noopener noreferrer"&gt;&lt;code&gt;networks&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Specify the networks used by the container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#ports" rel="noopener noreferrer"&gt;&lt;code&gt;ports&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Port mapping between host and container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/compose-file/#volumes" rel="noopener noreferrer"&gt;&lt;code&gt;volumes&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Specify a named volume or bind mount mapping between the host and container&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;View all possible Docker Compose options in the &lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here's a list of frequently used &lt;code&gt;docker-compose&lt;/code&gt; CLI commands:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/build/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose build&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Builds or rebuilds a service's image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/up/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose up&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Creates and starts service containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/down/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose down&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Stops containers and removes containers, images, and networks associated with a service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/exec/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose exec&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Execute a command in a container&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/images/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose images&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;List the images associated with services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/kill/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose kill&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Kills containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/logs/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose logs&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;View the logs of a service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/ps/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose ps&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;List all service containers and their state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/pull/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose pull&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Pull the image for a service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/push/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose push&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Push the image for a service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/rm/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose rm&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Removes stopped containers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/run/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose run&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Run a single command in a service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/start/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose start&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Start a service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://docs.docker.com/compose/reference/stop/" rel="noopener noreferrer"&gt;&lt;code&gt;docker-compose stop&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Stop a service&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;View all the &lt;code&gt;docker-compose&lt;/code&gt; command with &lt;code&gt;docker-compose help&lt;/code&gt; or in the &lt;a href="https://docs.docker.com/compose/reference/overview/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's possible to get command-line completion of &lt;code&gt;docker-compose&lt;/code&gt; commands by following &lt;a href="https://docs.docker.com/compose/completion/" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;. It should help to quickly type out commands and avoid typos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;Docker Compose file reference&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/compose/reference/overview/" rel="noopener noreferrer"&gt;Docker Compose CLI reference&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Managing environment variables
&lt;/h2&gt;

&lt;p&gt;Working with environment variables in Docker deserves its own section since it is not obvious how they work. When talking about &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-Linux-vps" rel="noopener noreferrer"&gt;environment variables&lt;/a&gt;, we are talking about variables that are globally accessible through any shell process in the Docker container and can be listed using the &lt;code&gt;env&lt;/code&gt; or &lt;code&gt;printenv&lt;/code&gt; shell commands.&lt;/p&gt;

&lt;p&gt;To verify environment variables are set in the shell of the Docker container, the most convenient way is to run &lt;code&gt;docker-compose exec container-name sh&lt;/code&gt; to open an interactive shell where all the environment variables can be listed using &lt;code&gt;env&lt;/code&gt; or &lt;code&gt;printenv&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first way environment variables can be set is in the &lt;code&gt;Dockerfile&lt;/code&gt; using the &lt;a href="https://docs.docker.com/engine/reference/builder/#env" rel="noopener noreferrer"&gt;&lt;code&gt;ENV&lt;/code&gt; instruction&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; &amp;lt;key&amp;gt;=&amp;lt;value&amp;gt; ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; TEST="value"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only will the variables set with the &lt;code&gt;ENV&lt;/code&gt; instruction be available as environment variables in the Docker container, but they will also be available to use in other instructions in the &lt;code&gt;Dockerfile&lt;/code&gt; by prefixing the name of the variable with &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next way to set environment variables is via the &lt;code&gt;docker run&lt;/code&gt; command using the &lt;code&gt;-e&lt;/code&gt; (&lt;code&gt;--env&lt;/code&gt;) option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt; my-app:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Environment variables can also be set with Docker compose and there is a &lt;a href="https://docs.docker.com/compose/environment-variables/" rel="noopener noreferrer"&gt;great guide&lt;/a&gt; on all the different ways to do so. To summarize the linked guide, environment variables in Docker Compose can be set for each service in the &lt;code&gt;docker-compose.yml&lt;/code&gt; file using the &lt;code&gt;environment&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web-app:
    environment:
      - TEST="value"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;docker-compose&lt;/code&gt; CLI will also automatically load environment variables found in &lt;code&gt;.env&lt;/code&gt; files that are in the same directory specified by the Docker Compose &lt;code&gt;build&lt;/code&gt; option. However, if the environment variable file is named other than &lt;code&gt;.env&lt;/code&gt;, then the file name should be specified using either the &lt;code&gt;--env-file&lt;/code&gt; CLI option of the &lt;code&gt;env_file&lt;/code&gt; option in the &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.dev up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  web-app:
    env_file: .env.dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If using the &lt;code&gt;docker-compose run&lt;/code&gt; command, pass environment variables using the &lt;code&gt;-e&lt;/code&gt; option.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose run &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;TEST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"value"&lt;/span&gt; web-app &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/compose/environment-variables/" rel="noopener noreferrer"&gt;&lt;em&gt;"Environment variables in Docker Compose"&lt;/em&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/builder/#env" rel="noopener noreferrer"&gt;&lt;code&gt;ENV&lt;/code&gt; instruction in &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/a&gt; in the Docker documentation&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-read-and-set-environmental-and-shell-variables-on-a-Linux-vps" rel="noopener noreferrer"&gt;Digital Ocean tutorial on environment variables&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deploying and running Docker applications
&lt;/h2&gt;

&lt;p&gt;There is a bunch of tooling that has been built around making it more manageable to deploy dockerized applications onto servers and make those applications accessible to the public. The choice of tooling used to deploy dockerized tooling depends on the scale of an app, the amount of control desired, the amount of complexity that is acceptable to manage, and the budget. This guide will list out 3 possible approaches to take to deploy dockerized applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dokku
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt; Side projects and early-stage startups&lt;/p&gt;

&lt;p&gt;For a low-cost solution where scalability is not a concern and a bit of manual server configuration is no issue, then &lt;a href="https://github.com/dokku/dokku" rel="noopener noreferrer"&gt;Dokku&lt;/a&gt; is a great solution. The way Dokku works is that it is installed on a cloud server (e.g. on &lt;a href="https://www.digitalocean.com/" rel="noopener noreferrer"&gt;Digital Ocean&lt;/a&gt; or &lt;a href="https://www.linode.com/" rel="noopener noreferrer"&gt;Linode&lt;/a&gt;) and can then be configured to run Docker applications. The basic steps are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Dokku on a server (Digital Ocean has &lt;a href="https://marketplace.digitalocean.com/apps/dokku" rel="noopener noreferrer"&gt;Dokku pre-installed on some servers&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;SSH into the server and pull down the application's image(s)&lt;/li&gt;
&lt;li&gt;Create an "app" within Dokku which will use one an image (create multiple apps to run multiple containers on a single server)&lt;/li&gt;
&lt;li&gt;Configure Dokku with domain names, SSL, databases, etc.&lt;/li&gt;
&lt;li&gt;Run the application(s) with Dokku&lt;/li&gt;
&lt;li&gt;Update the applications by pulling down new images and running a Dokku command (see &lt;a href="https://github.com/robertcoopercode/tech-job-hunt/blob/e2afe48f1a1f22755451b104abf01fc237687313/.github/workflows/dev-deploy.yml#L61-L65" rel="noopener noreferrer"&gt;this code for an example&lt;/a&gt; of this being done in the CI with GitHub actions)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get a more step-by-step outline of how to do this, see the &lt;a href="http://dokku.viewdocs.io/dokku/getting-started/installation/" rel="noopener noreferrer"&gt;Dokku documentation&lt;/a&gt; or this article on setting up &lt;a href="https://www.robertcooper.me/setup-dokku-digital-ocean" rel="noopener noreferrer"&gt;Dokku with Digital Ocean&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dokku is great if budget is a concern and a high level of control is desired, however, this is not as simple a solution as using Heroku or the Digital Ocean App Platform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://dokku.viewdocs.io/dokku/getting-started/installation/" rel="noopener noreferrer"&gt;Dokku documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.robertcooper.me/setup-dokku-digital-ocean" rel="noopener noreferrer"&gt;&lt;em&gt;"Set up Dokku on Digital Ocean"&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Heroku and Digital Ocean App Platform
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt; Small to medium-sized startups/companies&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt; and the &lt;a href="https://www.digitalocean.com/docs/app-platform/" rel="noopener noreferrer"&gt;Digital Ocean App Platform&lt;/a&gt; are solutions that handle a lot of the complexity related to setting up and deploying applications on servers while also automatically scaling applications on the fly. Both platforms allow for the deploying applications in Docker containers and make it easy to setup domains, SSL, and databases. Since Heroku and the Digital Ocean App Platform handle implementing some of the configurations, there may be some limitations encountered for more advanced server setups.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://devcenter.heroku.com/categories/deploying-with-docker" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/docs/app-platform/" rel="noopener noreferrer"&gt;Digital Ocean App Platform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Kubernetes
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Ideal for:&lt;/strong&gt; medium to large-sized startups/companies with large scale&lt;/p&gt;

&lt;p&gt;Perhaps the most popular name in the field of deploying dockerized applications is Kubernetes, which can be referred to as a "container orchestration system" responsible for deploying, scaling, and managing dockerized applications. Kubernetes can automatically scale apps by adding more servers/virtual machines and distribute traffic among those servers. The 3 big cloud providers (Amazon, Microsoft, Google) have offerings that integrate with Kubernetes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Elastic Kubernetes Service (EKS) (&lt;a href="https://aws.amazon.com/eks/" rel="noopener noreferrer"&gt;https://aws.amazon.com/eks/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Azure Kubernetes Service (AKS) (&lt;a href="https://azure.microsoft.com/en-us/services/kubernetes-service/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/en-us/services/kubernetes-service/&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Google Container Engine (GKE) (&lt;a href="https://cloud.google.com/kubernetes-engine" rel="noopener noreferrer"&gt;https://cloud.google.com/kubernetes-engine&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above offerings are called "managed Kubernetes" services because each cloud provider manages certain parts of the Kubernetes concerns, such as creating a Kubernetes cluster on AWS, Microsoft, or Google specific infrastructure.&lt;/p&gt;

&lt;p&gt;Kubernetes is great for large scale and complex applications, but small scale applications should try to avoid using Kubernetes if possible since it comes with a lot of configuration and complexity. Unless a user has a good understanding of servers and deployment-related things, Kubernetes has a steep learning curve and can't take up a lot of time that could be better spent on application development purposes. There is a lot of tooling surrounding Kubernetes itself (e.g. &lt;a href="https://helm.sh/" rel="noopener noreferrer"&gt;Helm&lt;/a&gt; and &lt;a href="https://kubernetes.io/docs/reference/kubectl/overview/" rel="noopener noreferrer"&gt;kubectl&lt;/a&gt;) that takes a lot of time to learn and be comfortable working with.&lt;/p&gt;

&lt;p&gt;For me details on the topic of whether Kubernetes should be used, I recommend reading this article title "&lt;a href="https://pythonspeed.com/articles/dont-need-kubernetes/" rel="noopener noreferrer"&gt;&lt;em&gt;“Let’s use Kubernetes!” Now you have 8 problems&lt;/em&gt;&lt;/a&gt;". &lt;strong&gt;Don't start addressing scaling issues until it becomes a problem.&lt;/strong&gt; When it does, &lt;a href="https://alexpareto.com/scalability/systems/2020/02/03/scaling-100k.html" rel="noopener noreferrer"&gt;here's a good article on how to scale apps starting from 1 user to 100k users&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=7bA0gTroJjw" rel="noopener noreferrer"&gt;Youtube - &lt;em&gt;"you need to learn Kubernetes RIGHT NOW!!"&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Avoiding the Docker command line
&lt;/h2&gt;

&lt;p&gt;Understandably, some people aren't too fond of working in the command line. Well, luckily, there are some great options for using Graphical User Interfaces (GUIs) along with Docker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker Desktop
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/desktop/" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt; ships with a GUI that interacts with the Docker Engine to perform some Docker related tasks, such as stopping containers, remove containers, and opening a shell inside a container.&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%2Fibrsrzb7b7n7sedt14cz.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%2Fibrsrzb7b7n7sedt14cz.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt;, one of the most popular text editors (&lt;a href="https://2019.stateofjs.com/other-tools/#text_editors" rel="noopener noreferrer"&gt;especially amongst JavaScript devs&lt;/a&gt;), has a great &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker" rel="noopener noreferrer"&gt;Docker extension&lt;/a&gt; that enables many Docker related tasks to be done without having to leave the editor.&lt;/p&gt;

&lt;p&gt;In addition to being able to view Docker images, containers, networks, and volumes, IntelliSense autocomplete functionality is available in &lt;code&gt;Dockerfile&lt;/code&gt;s and Docker Compose configuration files. Also, most common Docker commands are available via the command palette.&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%2Fydvluh185k9sluvpvd7j.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%2Fydvluh185k9sluvpvd7j.png" alt="Docker VS Code extension"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-the-docker-plugin-for-visual-studio-code" rel="noopener noreferrer"&gt;&lt;em&gt;"How To Use the Docker Plugin for Visual Studio Code"&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=bUhjY2L1iFc" rel="noopener noreferrer"&gt;YouTube - "VS Code Docker Extension - Overview"&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dockstation
&lt;/h3&gt;

&lt;p&gt;Dockstation is a full-fledged desktop application dedicated to serving as a Docker GUI. It provides a nice way to visualize Docker related information along with performing most Docker related tasks.&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%2Fm1ra98aborm2eb2c71mu.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%2Fm1ra98aborm2eb2c71mu.png" alt="Dockstation project view"&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%2Fi%2Fhd4xcftzyyz0bo7dul1z.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%2Fhd4xcftzyyz0bo7dul1z.png" alt="Dockstation stats view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging dockerized apps
&lt;/h2&gt;

&lt;p&gt;It's common for developers to opt to run some of their application's services locally outside of Docker to be able to run the services through their editor's debugger to have a better debugging experience. However, editors have started to add the ability to attach a debugger inside of a running Docker container, so there should not be a need to have to run services outside of Docker to take advantage of an editor's debugging capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visual Studio Code
&lt;/h3&gt;

&lt;p&gt;To debug containerized apps in Visual Studio code, the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker" rel="noopener noreferrer"&gt;Docker extension&lt;/a&gt; is required. The Docker extension currently only supports debugging Node.js, Python, and .NET Core applications inside Docker containers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/docs/containers/debug-common" rel="noopener noreferrer"&gt;Debug containerized apps&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  JetBrains IDEs
&lt;/h3&gt;

&lt;p&gt;There are many JetBrains IDEs and most of them have ways to run dockerized applications with debug capabilities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related resources&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/help/webstorm/node-with-docker.html" rel="noopener noreferrer"&gt;Node.js in Docker with WebStorm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/help/pycharm/using-docker-as-a-remote-interpreter.html" rel="noopener noreferrer"&gt;Docker with Pycharm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.jetbrains.com/help/idea/docker.html" rel="noopener noreferrer"&gt;Docker with IntelliJ&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Navigating the Docker documentation
&lt;/h2&gt;

&lt;p&gt;There's a lot of parts to the &lt;a href="https://docs.docker.com/" rel="noopener noreferrer"&gt;Docker documentation website&lt;/a&gt;, with getting started guides, release notes, manuals on how to use  Docker products, and more. Therefore it might not be obvious where to look for relevant documentation about some of the Docker-related stuff talked about in this article.&lt;/p&gt;

&lt;p&gt;I'm here to tell you that you will &lt;strong&gt;&lt;a href="https://docs.docker.com/reference/" rel="noopener noreferrer"&gt;likely want to be looking at the "Reference documentation"&lt;/a&gt;&lt;/strong&gt;. More specifically the following reference documentation pages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;Dockerfile reference&lt;/a&gt; (Lists out all available instructions that can be used in a Dockerfile)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.docker.com/compose/compose-file/" rel="noopener noreferrer"&gt;Docker Compose file reference&lt;/a&gt; (Lists out all the possible configuration parameters in a Docker Compose file)&lt;/li&gt;
&lt;li&gt;
&lt;a href="(https://docs.docker.com/engine/reference/commandline/cli/)"&gt;Docker CLI reference&lt;/a&gt; (All Docker CLI commands. Note that just running &lt;code&gt;docker help&lt;/code&gt; in the command line is also extremely helpful)&lt;/li&gt;
&lt;li&gt;
&lt;a href="(https://docs.docker.com/compose/reference/overview/)"&gt;Docker Compose CLI reference&lt;/a&gt; (All docker-compose CLI commands. &lt;code&gt;docker-compose help&lt;/code&gt; from the command line is also helpful)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://labs.play-with-docker.com/" rel="noopener noreferrer"&gt;"Play with Docker"&lt;/a&gt; is an online interactive playground where you can experiment with running Docker commands in the browser&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=bhBSlnQcq2k" rel="noopener noreferrer"&gt;Docker &amp;amp; Kubernetes Course on YouTube&lt;/a&gt; is a 4+ hour course that explains how to use both Docker and Kubernetes&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=eGz9DS-aIeY" rel="noopener noreferrer"&gt;YouTube - "you need to learn Docker RIGHT NOW!! // Docker Containers 101"&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>How to get your first 1000 reputation on Stack Overflow</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Mon, 10 Aug 2020 14:37:47 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/how-to-get-your-first-1000-reputation-on-stack-overflow-2glj</link>
      <guid>https://forem.com/robertcoopercode/how-to-get-your-first-1000-reputation-on-stack-overflow-2glj</guid>
      <description>&lt;p&gt;Stack Overflow: &lt;em&gt;The place where dreams come true.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, maybe a bit of an exaggeration, but developers get a lot of questions answered on Stack Overflow and it is probably the most frequently used tool by developers to help them get un-stuck while programming. This article will explain what Stack Overflow reputation is, why it matters, and how Stack Overflow users can get their first 1000 reputation.&lt;/p&gt;

&lt;p&gt;The reason for writing this article is because I recently passed the 1000 reputation threshold and I learned a lot on how to best gain reputation. At the time of writing, &lt;a href="https://stackoverflow.com/users/8360496/robert-cooper"&gt;I'm at 1510 reputation&lt;/a&gt;, which is not much compared to some, but I consider it to be a good achievement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Us4PwLnj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bnt8azr10jn72hkzv7w8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Us4PwLnj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/bnt8azr10jn72hkzv7w8.png" alt="Robert Cooper's current reputation of 1510."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Stack Overflow reputation?
&lt;/h2&gt;

&lt;p&gt;From the &lt;a href="https://stackoverflow.com/help/whats-reputation"&gt;Stack Overflow help article on reputation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reputation is a rough measurement of how much the community trusts you; it is earned by convincing your peers that you know what you’re talking about.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main way to gain reputation on Stack Overflow is to get your questions and answers upvoted by others. The breakdown is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Question is upvoted = +10 reputation&lt;/li&gt;
&lt;li&gt;Answer is upvoted = +10 reputation&lt;/li&gt;
&lt;li&gt;Answer is marked as accepted = +15 reputation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also gain additional reputation by answering questions that &lt;a href="https://stackoverflow.com/help/bounty"&gt;have bounties associated&lt;/a&gt; with them. Bounties are questions that will provide larger amounts of reputation for accepted answers. Bounties can range from +50 to +500 reputation.&lt;/p&gt;

&lt;p&gt;The bounty amount is taken from the question asker's own reputation. As an example, if a bounty is worth +100 reputation, then the question asker will have had to lose 100 of their own reputation in order to post the bounty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does reputation matter?
&lt;/h2&gt;

&lt;p&gt;As is true in real life, having a good reputation makes you more trustworthy and, in the case of Stack Overflow, it positions yourself as an authority on certain software development topics. If you visit a user's profile, you will be able to see the breakdown of their reputation by topics so you can better identify where a person's expertise lies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rKsYRFd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7p0hu7qxxqc98kqxneyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rKsYRFd2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/7p0hu7qxxqc98kqxneyv.png" alt="Reputation of Jon Skeet, the Stack Overflow user with the largest amount of reputation."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Reputation of &lt;a href="https://stackoverflow.com/users/22656/jon-skeet"&gt;Jon Skeet&lt;/a&gt;, the Stack Overflow user with the largest amount of reputation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In my opinion, having a high reputation on Stack Overflow can be beneficial if you're trying to make a positive impression on prospective employers or, if you're a freelancer, on prospective clients. Other than that, I'm not sure there is much to personally gain from having a high reputation on the site.&lt;/p&gt;

&lt;p&gt;Oh, I almost forgot to mention. You are also able to flex on your developer peers if you have a high reputation. That being said, if you decide to flex on others with your high Stack Overflow reputation, you will likely lose some real-life social reputation and respect.&lt;/p&gt;

&lt;p&gt;Stack Overflow reputation can be a bit overrated since some people that have been on the platform since its early days benefit from having asked/answered commonly asked questions before anyone else has and so they've had many years to accumulate reputation and continue to accumulate reputation for those answers/questions. This is further amplified by the fact that many questions on Stack Overflow are marked as duplicates of earlier asked questions and the duplicate question links back to the original.&lt;/p&gt;

&lt;p&gt;All that being said, accumulating 1000 reputation is, in my opinion, a good indicator that a person has a good grasp of certain topics related to software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  As a beginner, focus on asking questions
&lt;/h2&gt;

&lt;p&gt;My advice for gaining reputation depends on your experience level as a developer. If you are a fairly inexperienced developer, I would highly encourage you NOT to try and look for questions to answer, but rather focus on &lt;strong&gt;asking clear and detailed questions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As a beginner, you will surely encounter a lot of problems which is a great opportunity for you to ask questions. As a beginner, spending your time programming and running into problems you need to solve is the best way to learn and it will give you a lot of material for questions to be asked.&lt;/p&gt;

&lt;p&gt;Before asking a question on Stack Overflow, you should make an effort to research solutions to your problem since, in most cases, the answers to beginner-level questions are easily found on the internet.&lt;/p&gt;

&lt;p&gt;On the other hand, if you're inexperienced and you try to find questions to answer, what will likely happen is that you will find very few questions that you can confidently answer. Worse yet, you might try to provide an answer that you think has a chance of being correct, but is completely wrong. This not only doesn't help the question asker but will potentially lead to people downvoting your answer causing you to lose reputation. I have seen this happen on Stack Overflow and I'm personally guilty of doing this myself when I first started out answering questions as a beginner.&lt;/p&gt;

&lt;p&gt;Don't underplay how much asking questions can contribute to your Stack Overflow reputation. You get just as many reputation points when your question is upvoted as if your answer is upvoted. Also, since a lot of people on Stack Overflow post questions that are vague and very difficult to reproduce, if you're able to write questions that are clear and easily reproducible, users will appreciate it and will likely want to upvote the question to thank you for your effort.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--naOD5FZW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zvhs31csztfwi1sbzjuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--naOD5FZW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/zvhs31csztfwi1sbzjuj.png" alt="Breakdown of reputation by top questions for a user."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0zvfn9Wu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m3b4k1119xh70ll5jxrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0zvfn9Wu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m3b4k1119xh70ll5jxrg.png" alt="Breakdown of reputation by top answers for a user."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="https://stackoverflow.com/users/2873357/relm"&gt;This user&lt;/a&gt; mostly gained their reputation from asking questions as you can see by looking at their top-voted questions and answers.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I find that good questions for beginners to ask are ones that are related to a project they are working on and can be reproduced by others in a sandboxed environment. This is especially true for web applications since there are many good online tools you can use to demo your issue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://codesandbox.io/dashboard/home"&gt;Code Sandbox&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codepen.io/"&gt;Code Pen&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://jsfiddle.net/"&gt;JSFiddle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://repl.it/"&gt;Repl.it&lt;/a&gt; (Good choice for non-web languages like python, java, ruby, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not only does writing good questions on Stack Overflow help you build reputation, but it forces you to improve your written communication skills, which is hugely important in software engineering where you often need to collaborate with others. For example, being able to write descriptive pull requests on GitHub helps to communicate to your team the changes you are introducing through a code change and will have given others more confidence in what you are trying to achieve if they can better understand what you're trying to do.&lt;/p&gt;

&lt;p&gt;Here is a good article by Stack Overflow on how to ask a good question: &lt;a href="https://stackoverflow.com/help/minimal-reproducible-example"&gt;https://stackoverflow.com/help/minimal-reproducible-example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  As an experienced developer, focus on answering questions
&lt;/h2&gt;

&lt;p&gt;If you have a good amount of experience in a particular domain of software development, then the fastest way for you to gain reputation is to &lt;strong&gt;answer people's questions&lt;/strong&gt;. This is because you probably have a lot more answers that people are seeking than questions you may have to ask.&lt;/p&gt;

&lt;p&gt;When looking at questions to answer, you should first &lt;strong&gt;set up your list of watched tags&lt;/strong&gt;. By watching certain tags, you will be shown questions related to the tags you are watching. This means that you can focus on questions that you are more likely to have an answer to. For example, I have a lot of experience in some front-end developer-related topics, so I'm watching tags related to &lt;code&gt;frontend&lt;/code&gt;, &lt;code&gt;javascript&lt;/code&gt;, &lt;code&gt;reactjs&lt;/code&gt;, &lt;code&gt;typescript&lt;/code&gt;, and others.&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;My watched tags.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You are also able to mark some tags as "ignored", which prevents questions that contain those tags from showing up in your list of questions. I think this might be an underrated feature in helping people filter out questions. Personally, anytime time I see a question show up in my feed that is related to a topic I have no experience with, I add it to my list of ignored tags (therefore I have a lot of tags I'm ignoring).&lt;/p&gt;

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

&lt;p&gt;&lt;em&gt;My ignored tags.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using sandbox environments not only help question-askers demonstrate their issue, but it is a good tool to use to demonstrate your answers. If the question asker has used a sandbox tool of their own, it is usually possible to "fork" their sandbox and work on a solution to it, which you can link to in your answer.  Stack Overflow also has its own way to run code &lt;a href="https://stackoverflow.blog/2014/09/16/introducing-runnable-javascript-css-and-html-code-snippets/"&gt;right inside of Stack Overflow using "snippets"&lt;/a&gt;. Snippets allow you to run JavaScript, HTML, and CSS right inside of Stack Overflow and embed it in a question/answer. It is especially convenient to find a question that uses a snippet since there is a button to copy the snippet to an answer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jkcEhM5j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e0zmr3jyogc6hex92jhq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jkcEhM5j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/e0zmr3jyogc6hex92jhq.png" alt="Stack Overflow snippets found in questions allow users to copy the snippets to answers to quickly see the issue, debug the problem, and fix it."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Stack Overflow snippets found in questions allow users to copy the snippets to answers to quickly see the issue, debug the problem, and fix it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gaEX1j_r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s961okdejbj447bf7zrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gaEX1j_r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/s961okdejbj447bf7zrk.png" alt="A glimpse at my recent code sandboxes, which have all been used to help illustrate answers to questions on Stack Overflow."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A glimpse at my recent code sandboxes, which have all been used to help illustrate answers to questions on Stack Overflow.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;One thing that you should &lt;strong&gt;NOT&lt;/strong&gt; do is to "strategically downvote" other people's answers to improve your chances of having your answer accepted. I've seen this recommended in some places, but that is not at all helpful to the community and is a selfish thing to do. If you downvote answers that are actually correct/helpful, then that's not cool.&lt;/p&gt;




&lt;p&gt;I find it quite nice being able to help people on Stack Overflow and I think it's great that they have &lt;a href="https://en.wikipedia.org/wiki/Gamification"&gt;gamified&lt;/a&gt; their platform since it really encourages people to provide quality answers to questions in a timely manner. That being said, I wouldn't rely on Stack Overflow as a way to get better at programming. It's always been my opinion that the best way to get better at programming is to do more programming! Yes, you will likely learn a thing a two when trying to find answers to people's questions, but you will surely learn more by programming yourself.&lt;/p&gt;

</description>
      <category>stackoverflow</category>
    </item>
    <item>
      <title>Using ESLint and Prettier in a TypeScript Project</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Sat, 16 Feb 2019 16:49:11 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/using-eslint-and-prettier-in-a-typescript-project-53jb</link>
      <guid>https://forem.com/robertcoopercode/using-eslint-and-prettier-in-a-typescript-project-53jb</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally posted on &lt;a href="https://www.robertcooper.me/using-eslint-and-prettier-in-a-typescript-project"&gt;my blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When it comes to linting TypeScript code, there are two major linting options to choose from: &lt;a href="https://palantir.github.io/tslint/"&gt;TSLint&lt;/a&gt; and &lt;a href="https://eslint.org/"&gt;ESLint&lt;/a&gt;. TSLint is a linter than can only be used for TypeScript, while ESLint supports both JavaScript and TypeScript.&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://github.com/Microsoft/TypeScript/issues/29288#developer-productivity-tools-and-integration"&gt;TypeScript 2019 Roadmap&lt;/a&gt;, the TypeScript core team explains that &lt;strong&gt;ESLint has a more performant architecture than TSLint&lt;/strong&gt; and that they will &lt;strong&gt;only be focusing on ESLint&lt;/strong&gt; when providing editor linting integration for TypeScript. For that reason, I would recommend using ESLint for linting TypeScript projects.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting up ESLint to work with TypeScript
&lt;/h2&gt;

&lt;p&gt;First, install all the required dev dependencies:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin &lt;span class="nt"&gt;--dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/eslint"&gt;&lt;code&gt;eslint&lt;/code&gt;&lt;/a&gt;: The core ESLint linting library&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/@typescript-eslint/parser"&gt;&lt;code&gt;@typescript-eslint/parser&lt;/code&gt;&lt;/a&gt;: The parser that will allow ESLint to lint TypeScript code&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/@typescript-eslint/eslint-plugin"&gt;&lt;code&gt;@typescript-eslint/eslint-plugin&lt;/code&gt;&lt;/a&gt;: A plugin that contains a bunch of ESLint rules that are TypeScript specific&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next, add an &lt;code&gt;.eslintrc.js&lt;/code&gt; configuration file in the root project directory. Here is a sample configuration for a TypeScript project:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@typescript-eslint/parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Specifies the ESLint parser&lt;/span&gt;
  &lt;span class="na"&gt;extends&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="s1"&gt;plugin:@typescript-eslint/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Uses the recommended rules from the @typescript-eslint/eslint-plugin&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
 &lt;span class="na"&gt;parserOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;2018&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Allows for the parsing of modern ECMAScript features&lt;/span&gt;
    &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Allows for the use of imports&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs&lt;/span&gt;
    &lt;span class="c1"&gt;// e.g. "@typescript-eslint/explicit-function-return-type": "off",&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;&lt;strong&gt;Note:&lt;/strong&gt; I prefer using a JavaScript file for the &lt;code&gt;.eslintrc&lt;/code&gt; file (instead of a JSON file) as it supports comments that can be used to better describe rules.&lt;/p&gt;

&lt;p&gt;If using TypeScript with React, the &lt;a href="https://www.npmjs.com/package/eslint-plugin-react"&gt;&lt;code&gt;eslint-plugin-react&lt;/code&gt;&lt;/a&gt; dev dependency should be installed and the following configuration can be used:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@typescript-eslint/parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Specifies the ESLint parser&lt;/span&gt;
  &lt;span class="na"&gt;extends&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="s1"&gt;plugin:react/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Uses the recommended rules from @eslint-plugin-react&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin:@typescript-eslint/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Uses the recommended rules from @typescript-eslint/eslint-plugin&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;parserOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;2018&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Allows for the parsing of modern ECMAScript features&lt;/span&gt;
  &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Allows for the use of imports&lt;/span&gt;
  &lt;span class="na"&gt;ecmaFeatures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;jsx&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="c1"&gt;// Allows for the parsing of JSX&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs&lt;/span&gt;
    &lt;span class="c1"&gt;// e.g. "@typescript-eslint/explicit-function-return-type": "off",&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;react&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;detect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Tells eslint-plugin-react to automatically detect the version of React to use&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ultimately it's up to you to decide what rules you would like to extend from and which ones to use within the &lt;code&gt;rules&lt;/code&gt; object in your &lt;code&gt;.eslintrc.js&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Prettier to the mix
&lt;/h2&gt;

&lt;p&gt;What works well along with ESLint is &lt;a href="https://prettier.io/"&gt;prettier&lt;/a&gt;, which does a great job at handling code formatting. Install the required dev dependencies to get prettier working with ESLint:&lt;/p&gt;

&lt;p&gt;yarn add prettier eslint-config-prettier eslint-plugin-prettier --dev&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/prettier"&gt;&lt;code&gt;prettier&lt;/code&gt;&lt;/a&gt;: The core prettier library&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/eslint-config-prettier"&gt;&lt;code&gt;eslint-config-prettier&lt;/code&gt;&lt;/a&gt;: Disables ESLint rules that might conflict with prettier&lt;/li&gt;
&lt;li&gt;  &lt;a href="https://www.npmjs.com/package/eslint-plugin-prettier"&gt;&lt;code&gt;eslint-plugin-prettier&lt;/code&gt;&lt;/a&gt;: Runs prettier as an ESLint rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to configure prettier, a &lt;code&gt;.prettierrc.js&lt;/code&gt; file is required at the root project directory. Here is a sample &lt;code&gt;.prettierrc.js&lt;/code&gt; file:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;semi&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="na"&gt;trailingComma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;all&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;singleQuote&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="na"&gt;printWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;tabWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;4&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;Next, the &lt;code&gt;.eslintrc.js&lt;/code&gt; file needs to be updated:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;parser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@typescript-eslint/parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Specifies the ESLint parser&lt;/span&gt;
  &lt;span class="na"&gt;extends&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="s1"&gt;plugin:@typescript-eslint/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Uses the recommended rules from the @typescript-eslint/eslint-plugin&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;prettier/@typescript-eslint&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;plugin:prettier/recommended&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;parserOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;ecmaVersion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="mi"&gt;2018&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Allows for the parsing of modern ECMAScript features&lt;/span&gt;
    &lt;span class="na"&gt;sourceType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;module&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// Allows for the use of imports&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;The advantage of having prettier setup as an ESLint rule using &lt;code&gt;eslint-plugin-prettier&lt;/code&gt; is that code can automatically be fixed using ESLint's &lt;code&gt;--fix&lt;/code&gt; option.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automatically Fixing Code (VS Code)
&lt;/h2&gt;

&lt;p&gt;For a good developer experience, it's useful to setup your editor to automatically run ESLint's automatic fix command (i.e. &lt;code&gt;eslint --fix&lt;/code&gt;) whenever a file is saved. Since i'm using VS Code, here is the config required in the &lt;code&gt;settings.json&lt;/code&gt; file in VS Code to get automatic fixing whenever saving a file:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint.autoFixOnSave&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eslint.validate&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;javascript&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;javascriptreact&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;language&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;typescript&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;autoFix&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;language&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;typescriptreact&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;autoFix&lt;/span&gt;&lt;span class="dl"&gt;"&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="p"&gt;],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you've also set the &lt;code&gt;editor.formatOnSave&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; in your &lt;code&gt;settings.json&lt;/code&gt;, you'll need to add the following config to prevent running 2 formatting commands on save for JavaScript and TypeScript files:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="s2"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"[javascript]"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"[javascriptreact]"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"[typescript]"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s2"&gt;"[typescriptreact]"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;






&lt;p&gt;And there you have it. That's how you can lint a TypeScript project using ESLint. If you want to make sure all the files you commit to git pass the ESLint checks, take a look at &lt;a href="https://github.com/okonet/lint-staged"&gt;lint-staged&lt;/a&gt;, which can run ESLint on files being commited.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>developertools</category>
    </item>
    <item>
      <title>Get Started With TypeScript in 2019</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Sun, 20 Jan 2019 18:26:21 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/get-started-with-typescript-in-2019-6hd</link>
      <guid>https://forem.com/robertcoopercode/get-started-with-typescript-in-2019-6hd</guid>
      <description>&lt;h1&gt;
  
  
  Get Started With TypeScript in 2019
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally posted on &lt;a href="https://www.robertcooper.me/get-started-with-typescript-in-2019" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Based on the &lt;a href="https://insights.stackoverflow.com/survey/2018/" rel="noopener noreferrer"&gt;Stack Overflow Developer survey in 2018&lt;/a&gt;, TypeScript is more “loved” as a programming language than JavaScript. The reason TypeScript is so loved amongst JavaScript developers is because adding types to JavaScript allows you to spot errors before running your code. The errors provided by the TypeScript compiler will give a good indication of how an error can be fixed. Adding types to JavaScript also allows code editors to provide some more advanced features, such as code completion, project-wide refactoring, and automatic module importing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04sy6ibyxor41ewh5hdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04sy6ibyxor41ewh5hdv.png" alt="Results of the most loved programming languages survey question from the 2018 Stack Overflow Survey" width="800" height="446"&gt;&lt;/a&gt;Results of the “most loved programming languages” survey question from the &lt;a href="https://insights.stackoverflow.com/survey/2018/#most-loved-dreaded-and-wanted" rel="noopener noreferrer"&gt;2018 Stack Overflow Developer Survey&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Learning TypeScript might seem intimidating if you come to think of it as a completely new programming language. However, TypeScript is just an added layer to JavaScript and you by no means have to know every bit of syntax that comes along with TypeScript before you can start using it. TypeScript allows you to easily convert a JavaScript file by changing the file extension from &lt;code&gt;.js&lt;/code&gt; to &lt;code&gt;.ts&lt;/code&gt; and all the code will compile properly as TypeScript. You can configure TypeScript to be more restrictive if you want to enforce a larger percentage of type coverage in your TypeScript files, but that can be done once you get more familiar with the language.&lt;/p&gt;

&lt;p&gt;This article aims to bring you up to speed with around &lt;strong&gt;95% of the scenarios&lt;/strong&gt; you will typically encounter in a standard TypeScript project. For that last 5%, well, Google is your friend and I’ve added links to useful TypeScript resources at the bottom of the article.&lt;/p&gt;




&lt;h3&gt;
  
  
  Setting Up TypeScript
&lt;/h3&gt;

&lt;p&gt;Of course, to begin writing TypeScript that compiles correctly, a properly configured development environment is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install the TypeScript compiler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To start off, the TypeScript compiler will need to be installed in order to convert TypeScript files into JavaScript files. To do this, TypeScript can either be installed globally (available anywhere in your file system) or locally (only available at the project level).&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="c"&gt;# NPM Installation Method&lt;/span&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--global&lt;/span&gt; typescript &lt;span class="c"&gt;# Global installation&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript &lt;span class="c"&gt;# Local installation&lt;/span&gt;

&lt;span class="c"&gt;# Yarn Installation Method&lt;/span&gt;

yarn global add typescript &lt;span class="c"&gt;# Global installation&lt;/span&gt;
yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; typescript &lt;span class="c"&gt;# Local installation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Commands to run from the command line to install TypeScript globally or locally on your computer&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Make sure your editor is setup to support TypeScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You’ll want to make sure your editor is properly configured to work with TypeScript. For example, you may need to install a plugin (such as &lt;a href="https://atom.io/packages/atom-typescript" rel="noopener noreferrer"&gt;atom-typescript&lt;/a&gt; if using the atom editor), in order to fully take advantage of TypeScript in your editor. If using VS Code, TypeScript support is built-in, so there are no extensions required 😎.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Create a&lt;/strong&gt; &lt;code&gt;**tsconfig.json**&lt;/code&gt; &lt;strong&gt;file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;tsconfig.json&lt;/code&gt; file is used to configure TypeScript project settings. The &lt;code&gt;tsconfig.json&lt;/code&gt; file should be put in the project's root directory. The file allows you to configure the TypeScript compiler with different options.&lt;/p&gt;

&lt;p&gt;You can have the &lt;code&gt;tsconfig.json&lt;/code&gt; contain an empty JSON object if you just want to get TypeScript to work, but if you need the TypeScript compiler to behave differently (such as output transpiled JavaScript files in a specific output directory), you can &lt;a href="https://www.typescriptlang.org/docs/handbook/compiler-options.html" rel="noopener noreferrer"&gt;read more&lt;/a&gt; about which settings can be configured.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can also run the &lt;code&gt;_tsc --init_&lt;/code&gt; to generate a &lt;code&gt;_tsconfig.json_&lt;/code&gt; file with some default options set for you and a bunch of other options commented out&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;4. Transpile TypeScript to JavaScript&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to transpile your TypeScript code to JavaScript, the &lt;code&gt;tsc&lt;/code&gt; command needs to be run in the terminal. Running &lt;code&gt;tsc&lt;/code&gt; will have the TypeScript compiler search for the &lt;code&gt;tsconfig.json&lt;/code&gt; file which will determine the project's root directory as well as which options to use when compiling the TypeScript and transpiling &lt;code&gt;.ts&lt;/code&gt; files to &lt;code&gt;.js&lt;/code&gt; files.&lt;/p&gt;

&lt;p&gt;To quickly test that the setup works, you can create a test TypeScript file and then run &lt;code&gt;tsc&lt;/code&gt; in the command line and see if a JavaScript file is generated beside the TypeScript file.&lt;/p&gt;

&lt;p&gt;For example, this TypeScript file…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Good day &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Daniel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example TypeScript syntax&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Should transpile to this JavaScript file…&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;var&lt;/span&gt; &lt;span class="nx"&gt;greeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Good day &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Daniel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;JavaScript file that gets generated from transpiling TypeScript&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’d like for the TypeScript compiler to watch for changes in your TypeScript files and automatically trigger the transpilation of &lt;code&gt;.ts&lt;/code&gt; to &lt;code&gt;.js&lt;/code&gt; files, you can run the &lt;code&gt;tsc -p&lt;/code&gt;. command in your project’s repository.&lt;/p&gt;

&lt;p&gt;In VS Code, you can use &lt;code&gt;⌘⇧B&lt;/code&gt; to bring up a menu that can run the transpiler in either normal or watch modes (&lt;code&gt;tsc:build&lt;/code&gt; or &lt;code&gt;tsc:watch&lt;/code&gt;, respectively).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiaxsi3qv71e1wqezuwu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiaxsi3qv71e1wqezuwu9.png" alt="The VS Code build tasks menu that can be brought up using ⌘⇧B" width="800" height="151"&gt;&lt;/a&gt;The VS Code build tasks menu that can be brought up using &lt;code&gt;⌘⇧B&lt;/code&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Understanding Static and Dynamic Types
&lt;/h3&gt;

&lt;p&gt;JavaScript comes with 7 &lt;em&gt;dynamic&lt;/em&gt; types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Undefined&lt;/li&gt;
&lt;li&gt;  Null&lt;/li&gt;
&lt;li&gt;  Boolean&lt;/li&gt;
&lt;li&gt;  Number&lt;/li&gt;
&lt;li&gt;  String&lt;/li&gt;
&lt;li&gt;  Symbol&lt;/li&gt;
&lt;li&gt;  Object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above types are called &lt;em&gt;dynamic&lt;/em&gt; since they are used at runtime.&lt;/p&gt;

&lt;p&gt;TypeScript brings along &lt;em&gt;static&lt;/em&gt; types to the JavaScript language, and those types are evaluated at compile time (without having to run the code). &lt;em&gt;Static&lt;/em&gt; types are what predict the value of &lt;em&gt;dynamic&lt;/em&gt; types and this can help warn you of possible errors without having to run the code.&lt;/p&gt;




&lt;h3&gt;
  
  
  Basic Static Types
&lt;/h3&gt;

&lt;p&gt;Alright, let’s dive into the syntax of TypeScript. What follows are the most commonly seen types in TypeScript.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I’ve left out the &lt;code&gt;_never_&lt;/code&gt; and &lt;code&gt;_object_&lt;/code&gt; types since, in my experience, they are not very commonly used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;boolean&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The simple &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt; values you've come to know and love.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isAwesome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;boolean type annotation&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;string&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Textual data surrounded in either single quotes (&lt;code&gt;'&lt;/code&gt;), double quotes (&lt;code&gt;"&lt;/code&gt;), or back ticks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chris&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;breed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Border Collie&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;string type annotation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If using back ticks, the string is called a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals" rel="noopener noreferrer"&gt;&lt;em&gt;template literal&lt;/em&gt;&lt;/a&gt; and expressions can be interpolated within them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;punchline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Because it was free-range.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;joke&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
    Q: Why did the chiken cross the road?
    A: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;punchline&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;string type annotation with the use of template literals&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;number&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Any floating point number is given the type of &lt;code&gt;number&lt;/code&gt;. The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Numbers_and_dates#Numbers" rel="noopener noreferrer"&gt;four types of number literals&lt;/a&gt; that are supported as part of TypeScript are &lt;em&gt;decimal&lt;/em&gt;, &lt;em&gt;binary&lt;/em&gt;, &lt;em&gt;octal&lt;/em&gt; and &lt;em&gt;hexadecimal&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;decimalNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;binaryNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mb"&gt;0b101010&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 42&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;octalNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mo"&gt;0o52&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 42&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;hexadecimalNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x2a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;number type annotation&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If the binary, octal, and hexadecimal numbers confuse you, you’re not alone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;array&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Array types in TypeScript can be written in two ways. The first way requires that &lt;code&gt;[]&lt;/code&gt; be postfixed to the type of elements that are found in the array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myPetFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rocket&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="s1"&gt;fluffly&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="s1"&gt;harry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;array of strings using the square bracket notation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The alternative way to write &lt;code&gt;Array&lt;/code&gt; types is to use Array followed by the type of elements that are found in the array (within angle brackets).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myPetFamily&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rocket&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="s1"&gt;fluffly&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="s1"&gt;harry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;array of strings using the angle bracket notation&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;tuple&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;A &lt;code&gt;tuple&lt;/code&gt; is an array that contains a fixed number of elements with associated types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;myFavoriteTuple&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;myFavoriteTuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chair&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&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="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;myFavoriteTuple&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&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="c1"&gt;// ❌ - The first element should be a string, not a number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Declaring a tuple with 3 elements and then assigning values to the tuple&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;enum&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;An &lt;code&gt;enum&lt;/code&gt; is a way to associate names to a constant value, which can be either a number or a string. Enums are useful when you want to have a set of distinct values that have a descriptive name associated with it.&lt;/p&gt;

&lt;p&gt;By default, enums are assigned numbers that start at &lt;code&gt;0&lt;/code&gt; and increase by &lt;code&gt;1&lt;/code&gt; for each member of the enum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Sizes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Small&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Medium&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Small&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 0&lt;/span&gt;
&lt;span class="nx"&gt;Sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Medium&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 1&lt;/span&gt;
&lt;span class="nx"&gt;Sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Large&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of an enum starting at 9&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The first value can be set to a value other than &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;Sizes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Small&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Medium&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;Sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Small&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 1&lt;/span&gt;
&lt;span class="nx"&gt;Sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Medium&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 2&lt;/span&gt;
&lt;span class="nx"&gt;Sizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Large&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of the enum starting at a value other than 0&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Enums are by default assigned numbers, however, string values can also be assigned to an enum.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;ThemeColors&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Primary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Secondary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;secondary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Dark&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;DarkSecondary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;darkSecondary&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of an enum with string values&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;any&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;If the type of a variable is not known and we don’t want the type checker to complain at compilation time, then the type of &lt;code&gt;any&lt;/code&gt; can be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;whoKnows&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// assigned a number&lt;/span&gt;

&lt;span class="nx"&gt;whoKnows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a beautiful string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// can be reassigned to a string&lt;/span&gt;
&lt;span class="nx"&gt;whoKnows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// can be reassigned to a boolean&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of the any type&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;any&lt;/code&gt; will likely frequently be used when starting out with TypeScript. However, it's best to try to reduce the usage of &lt;code&gt;any&lt;/code&gt; since the usefulness of TypeScript decreases when the compiler isn't aware of the types associated with variables.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;void&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;When there is no type associated with something, the &lt;code&gt;void&lt;/code&gt; type should be used. It is most commonly used when specifying the return value of a function that doesn't return anything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;darkestPlaceOnEarth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Marianas Trench&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of using the void type&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;Both &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; correspond to the types of the &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; values you might see in JavaScript. These types aren't very useful when used on their own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;anUndefinedVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;aNullVariable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of how the null and undefined types could be used&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By default the &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; types are &lt;em&gt;subtypes&lt;/em&gt; of all other types, meaning that a variable of type &lt;code&gt;string&lt;/code&gt; can be assigned a value of &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. This is often undesirable behavior and thus it’s usually recommended to set the &lt;code&gt;strictNullChecks&lt;/code&gt; compiler option in a &lt;code&gt;tsconfig.json&lt;/code&gt; file to &lt;code&gt;true&lt;/code&gt;. Setting the &lt;code&gt;strictNullChecks&lt;/code&gt; option to &lt;code&gt;true&lt;/code&gt; makes it so that &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;undefined&lt;/code&gt; need to be explicitly set as a type for a variable.&lt;/p&gt;




&lt;h3&gt;
  
  
  Type Inference
&lt;/h3&gt;

&lt;p&gt;Fortunately, you don’ have to specify types absolutely everywhere in your code because TypeScript has what is called &lt;em&gt;Type Inference&lt;/em&gt;. Type inference is what the TypeScript compiler uses to automatically determine types.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Type Inference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TypeScript can infer types during variable initialization, when default parameter values are set, and while determining function return values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Variable initialization&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// x is given the number type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of type inference where the x variable has an inferred type of number&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the above example, &lt;code&gt;x&lt;/code&gt; is assigned a number, TypeScript associates the &lt;code&gt;x&lt;/code&gt; variable with a type of &lt;code&gt;number&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Default function parameters&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tweetLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A default tweet&lt;/span&gt;&lt;span class="dl"&gt;'&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="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;&lt;em&gt;An inferred type of string is given to the message parameter&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the &lt;code&gt;message&lt;/code&gt; parameter is assigned a default value which is of type &lt;code&gt;string&lt;/code&gt;, so therefore the TypeScript compiler infers that &lt;code&gt;message&lt;/code&gt; is of type &lt;code&gt;string&lt;/code&gt; and therefore doesn’t throw a compilation error when the &lt;code&gt;length&lt;/code&gt; property is being accessed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&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;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - length is not a property of number types&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An inferred type of number is assigned to the return value of the add function based on the types of the function’s parameters&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the above example, since TypeScript is told that both parameters to the &lt;code&gt;add&lt;/code&gt; function have a type of &lt;code&gt;number&lt;/code&gt;, it can infer that the return type will also be a &lt;code&gt;number&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best Common Type Inference&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a type is being inferred from multiple possible types, TypeScript uses a “best common type” algorithm to pick a type that works with all the other candidates.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nope&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - type 'string' is neither of type 'number' or 'null'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The best common type algorithm determines that only number and null types should be allowed as elements to the list array&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the above example, the array is composed of both &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt; types, and therefore TypeScript expects only &lt;code&gt;number&lt;/code&gt; and &lt;code&gt;null&lt;/code&gt; values to be a part of the array.&lt;/p&gt;




&lt;h3&gt;
  
  
  Type Annotation
&lt;/h3&gt;

&lt;p&gt;When the Type Inference system is not enough, you will need to declare types on variables and objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;All the types introduced in the &lt;em&gt;Basic Static Types&lt;/em&gt; section can be declared using a &lt;code&gt;:&lt;/code&gt; followed by the name of the type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;aBoolean&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;aNumber&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;aString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;woohoo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Examples of annotating basic types&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arrays&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As shown in the section talking about the &lt;code&gt;array&lt;/code&gt; type, arrays can be annotated one of two ways.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// First method is using the square bracket notation&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;messageArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&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="s1"&gt;my name is fred&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="s1"&gt;bye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// Second method uses the Array keyword notation&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;messageArray&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello&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="s1"&gt;my name is fred&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="s1"&gt;bye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Annotating arrays&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interfaces&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One way to put together multiple type annotations is by using an interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mammal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;

&lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&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="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - kind should be a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Annotating types using an interface&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type Alias&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To make things confusing, TypeScript also allows you to specify multiple type annotations using a type alias.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Animal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mammal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;

&lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&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="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - kind should be a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Annotating types using a type alias&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What seems to be the best practice in terms of using an interface or a type alias is that you should generally just pick either &lt;code&gt;interface&lt;/code&gt; or &lt;code&gt;type&lt;/code&gt; in your codebase and be consistent. However, if writing a 3rd party public API that can be used by others, use an &lt;code&gt;interface&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;If you want to get a more detailed comparison between the type alias and an interface, I would recommend &lt;a href="https://medium.com/@martin_hotell/interface-vs-type-alias-in-typescript-2-7-2a8f1777af4c" rel="noopener noreferrer"&gt;this article&lt;/a&gt; by Matin Hochel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inline Annotations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of creating a re-usable interface, it might be more appropriate to annotate a type inline instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mammal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;

&lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;kind&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="na"&gt;weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - kind should be a string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Using an inline type annotation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generics&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are situations where the specific type of a variable doesn’t matter, but a relationship between the types of different variables should be enforced. For those cases, generic types should be used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;len&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elem&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;newArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; ['hi', 'hi', 'hi']&lt;/span&gt;

&lt;span class="nx"&gt;newArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;newArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="c1"&gt;// ❌ - only strings can be added to the array&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Using generic types to define type relationships&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The above example has a generic type &lt;code&gt;T&lt;/code&gt; that corresponds to the type of the second argument passed to the &lt;code&gt;fillArray&lt;/code&gt; function. The second argument passed to the &lt;code&gt;fillArray&lt;/code&gt; function is a string, and therefore the created array will have all of its elements set to have a type of &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It should be noted that it is by convention that single letters are used for generic types (e.g. &lt;code&gt;T&lt;/code&gt; or &lt;code&gt;K&lt;/code&gt;). However, there is nothing stopping your from using more descriptive names for your generic types. Here is the above example with a more descriptive name for the supplied generic type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArrayElementType&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;len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;elem&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ArrayElementType&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="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ArrayElementType&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;len&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;fill&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elem&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;newArray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fillArray&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; ['hi', 'hi', 'hi']&lt;/span&gt;

&lt;span class="nx"&gt;newArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bye&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;newArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&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="c1"&gt;// ❌ - only strings can be added to the array&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Using more descriptive names for generic types&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Union Type&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In scenarios where a type can be one of multiple types, a union type is used by separating the different type options with a &lt;code&gt;|&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The `name` parameter can be either a string or null&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sayHappyBirthdayOnFacebook&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Happy birthday!&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;else&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Happy birthday &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="nf"&gt;sayHappyBirthdayOnFacebook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; "Happy birthday!"&lt;/span&gt;
&lt;span class="nf"&gt;sayHappyBirthdayOnFacebook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jeremy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; "Happy birthday Jeremy!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An example of a union type annotation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Intersection Type&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An intersection type uses the &lt;code&gt;&amp;amp;&lt;/code&gt; symbol to combine multiple types together. This is different than the union type, as a union type says "the resulting type is &lt;strong&gt;one&lt;/strong&gt; of the listed types" whereas the intersection type says "the resulting type is the combination of all listed types".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Student&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;companyId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Student&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;21&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;companyId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SP302334&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;10033402&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Henry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - name does not exist in Student &amp;amp; Employee&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An example of an intersection type annotation&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tuple Type&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Tuples are annotated using a &lt;code&gt;:&lt;/code&gt; followed by a comma separated list of types within square brackets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&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="s1"&gt;banana&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;8.75&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ✅&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&lt;/span&gt;&lt;span class="dl"&gt;'&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="mf"&gt;8.75&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - the second argument should be of type string&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;apple&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="s1"&gt;banana&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;10.33&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt; &lt;span class="c1"&gt;// ❌ - the tuple specifies a length of 3, not 4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Annotating a variable using a tuple type&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional Types&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There may be instances where a function parameter or object property is optional. In those cases, a &lt;code&gt;?&lt;/code&gt; is used to denote these optional values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Optional function parameter&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;callMom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;message&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hi mom. Love you. Bye.&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;else&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&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="c1"&gt;// Interface describing an object containing an optional property&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;favoriteColor&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// This property is optional&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Defining optional types&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Useful Resources
&lt;/h3&gt;

&lt;p&gt;For the parts of TypeScript that weren’t covered in this article, I recommend the following resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/basic-types.html" rel="noopener noreferrer"&gt;TypeScript Handbook (Official TypeScript docs)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://basarat.gitbooks.io/typescript/content/docs/getting-started.html" rel="noopener noreferrer"&gt;TypeScript Deep Dive (Online TypeScript Guide)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://2ality.com/2018/04/type-notation-typescript.html" rel="noopener noreferrer"&gt;Understanding TypeScript’s Type Annotation (Great introductory TypeScript article)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Refreshing My Personal Website</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Tue, 01 Jan 2019 02:03:32 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/refreshing-my-personal-website-17ie</link>
      <guid>https://forem.com/robertcoopercode/refreshing-my-personal-website-17ie</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Originally posted &lt;a href="https://www.robertcooper.me/refreshing-my-personal-website"&gt;on my blog&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've decided to redo my website, yet again. This is the 3rd or 4th iteration of my website.&lt;/p&gt;

&lt;p&gt;Here were the motivations and goals for the redesign:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Host my blog articles on my own website
&lt;/h4&gt;

&lt;p&gt;I've been writting a lot on both &lt;a href="https://medium.com/@robertcooper_rc"&gt;Medium&lt;/a&gt; and a bit on &lt;a href="https://dev.to/robertcoopercode"&gt;Dev Community&lt;/a&gt;, but I want to have a bit more control in the design and presentation of my blog posts. One of my biggest gripes with Medium is the lack of syntax highlighting for code blocks.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Better highlight past projects
&lt;/h4&gt;

&lt;p&gt;In 2019, I want to work with a few clients on a part-time basis to supplement the income I make through my full-time job. The first step to doing that was to make sure I can showcase some of my past work in a favorable light.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. New tech stack
&lt;/h4&gt;

&lt;p&gt;My previous website was using gulp to build HTML pages from templated &lt;a href="https://pugjs.org/api/getting-started.html"&gt;pug files&lt;/a&gt;. This wasn't that bad since I only had one page on the website, so there wasn't a need to move between pages. However, now that I was going to include a blog, I was going to have to have multiple pages on the website and thus I wanted to use React to get the performance associated with a single page application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design
&lt;/h2&gt;

&lt;p&gt;So with those three goals in mind I started to research blogs that I admired. I made sure to screenshot and anotate any elements that stood out to me. I gathered all those screenshots in my design app of choice: &lt;a href="https://www.figma.com/"&gt;Figma&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qBbh6kl1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dr1gor93c0rvz8yerbf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qBbh6kl1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dr1gor93c0rvz8yerbf5.png" alt="A collection of screenshots from the blogs and websites that I admire."&gt;&lt;/a&gt;&lt;/p&gt;
A collection of screenshots from the blogs and websites that I admire.



&lt;p&gt;After I gathered all the pieces of inspiration, I went ahead and designed my own website. I knew I wanted to have both a light and dark theme to my website, so I made sure to design both variations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pT4duVgB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6ocqwlkjh1vxlltt9ega.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pT4duVgB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6ocqwlkjh1vxlltt9ega.png" alt="The designs for both light and dark theme pages of my new website."&gt;&lt;/a&gt;&lt;/p&gt;
The designs for both light and dark theme pages of my new website.



&lt;p&gt;The reason why I create design mockups instead of just coding the site straight away is so that I can quickly test out which designs look good. I find that I end up doing a few design interations before coming up with a final design. Doing those different variations in code rather than in a design software would take much longer. I also find it helps me better organize my work when I design the project before going into the code, and it ultimately saves me time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Home Page
&lt;/h2&gt;

&lt;p&gt;The home page, being the first place site visitors land when they visit my site, includes a short description of who I am, the blog articles I've recently written, as well as a preview of the recent projects I've worked on. I made sure to animate elements on the page, using the &lt;a href="https://github.com/michalsnik/aos"&gt;animate on scroll library&lt;/a&gt;, to make the experience slightly more enjoyable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_usvl0W9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9d347s42pvlo929ktwv0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_usvl0W9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/9d347s42pvlo929ktwv0.gif" alt="The home page elements fade into the page as a user scrolls scroll."&gt;&lt;/a&gt;&lt;/p&gt;
The home page elements fade into the page as a user scrolls.



&lt;p&gt;I've included a headshot of myself and I tried to crop out all of the background from the image. Unfortunately, I don't have the design skills required to get rid of some of the white background from my hair and it is prooving to be quite the annoyance every time I see it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--86j8-uZG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1ybo5h026hx59hgzslpr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--86j8-uZG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/1ybo5h026hx59hgzslpr.png" alt="Lingering white background that remains on Robert's headshot image."&gt;&lt;/a&gt;&lt;/p&gt;
Lingering white background that remains on the headshot image 😑



&lt;h2&gt;
  
  
  Projects
&lt;/h2&gt;

&lt;p&gt;I've created a page to better showcase my past projects. Each app is presented in a similar way, with screenshots of the apps found within desktop/mobile device frames. Each project is also given it's own section with a short description along with keywords indicating the main technologies used for the projects. A call to action section is found at the bottom of the page for any visitors interested in working together on a project.&lt;/p&gt;

&lt;p&gt;In the future, I plan to create full pages for each project in order to present them as full blown case studies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OoZ06Dwx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/940036o1p0nh4vey6iar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OoZ06Dwx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/940036o1p0nh4vey6iar.png" alt="The new projects page of the website showing projects for the React Montreal Meetup group, the Meat Journal mobile app, and an ecommerce Shopify theme called Daisies and Dandelions."&gt;&lt;/a&gt;&lt;/p&gt;
The new projects page of the website showcases three recent projects and a call to action link at the bottom of the page.



&lt;h2&gt;
  
  
  Blog
&lt;/h2&gt;

&lt;p&gt;The blog is where things get exciting technology wise. The website is built with React and &lt;a href="https://www.gatsbyjs.org/"&gt;Gatsby&lt;/a&gt;. I'm also using &lt;a href="https://gatsby-mdx.netlify.com/"&gt;gatsby-mdx&lt;/a&gt; which allows me to write my blog posts using MDX. &lt;a href="https://github.com/mdx-js/mdx"&gt;MDX&lt;/a&gt; is a different flavour of Markdown which allows for the use of JSX and React components to coexist with markdown in the same file.&lt;/p&gt;

&lt;p&gt;If I want to include a custom React component into a blog post to make the post more interactive, I can now do that in MDX. As an example, I can embed the theme switcher component I'm using for my website right into this post:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;See this blog post &lt;a href="https://www.robertcooper.me/refreshing-my-personal-website"&gt;on my website&lt;/a&gt; to see the embbeded React component.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I'm quite excited to take advantage of the power of MDX in some of my future blog articles.&lt;/p&gt;

&lt;p&gt;Another feature I've added to my blog is the horizontal progress bar indicating a user's progress through a blog post. I've seen this UI pattern on some other blogs and have enjoyed it myself.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PwKax715--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j77yat6mapw62szu00v5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PwKax715--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/j77yat6mapw62szu00v5.gif" alt="An horizontal progress bar at the top of a blog article indicates how much further a user needs to scroll to reach the bottom of the page."&gt;&lt;/a&gt;&lt;/p&gt;
An horizontal progress bar at the top of a blog article indicates how much further a user needs to scroll to reach the bottom of the page.



&lt;p&gt;I've also include a comment section to blog posts using the Disqus embed. This was surprisingly easy to incorporate into the website using &lt;a href="https://github.com/disqus/disqus-react"&gt;disqus-react&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dark / Light Theme
&lt;/h2&gt;

&lt;p&gt;Perhaps my favourite part of the website is the ability to toggle between a dark and light themes. I'm using &lt;a href="https://www.styled-components.com/"&gt;Styled Components&lt;/a&gt; to manage the styles on my website and it fortunately has great a &lt;a href="https://www.styled-components.com/docs/advanced#theming"&gt;API for managing theming&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1jYPTa5y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mcvzu0obz59yl2gojiz2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1jYPTa5y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/mcvzu0obz59yl2gojiz2.gif" alt="Toggling between dark and light theme through a toggle switch found in the main menu."&gt;&lt;/a&gt;&lt;/p&gt;
Toggling between dark and light theme.



&lt;p&gt;I'd like to point out that the design and functionality of the theme toggle switch was all taken from &lt;a href="https://twitter.com/thekitze"&gt;@thekitze&lt;/a&gt;'s Twizzy App &lt;a href="https://twizzy.app/"&gt;landing page&lt;/a&gt;. I'm always thankful when talented people like this make their projects open source to allow others to benefit.&lt;/p&gt;




&lt;p&gt;I hope to continue to make incremental improvements to my website. Some of the things I'd like to add include unit testing, end to end testing, and an RSS feed to the website. There are also a few bugs I need to squash 👞🐜.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/robertcoopercode/personal-website"&gt;See the source code.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>portfolio</category>
      <category>gatsby</category>
      <category>react</category>
      <category>design</category>
    </item>
    <item>
      <title>From Idea to App Store: Building My First iOS App With React Native</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Mon, 22 Oct 2018 23:11:42 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/from-idea-to-app-store-building-my-first-ios-app-with-react-native-1ej7</link>
      <guid>https://forem.com/robertcoopercode/from-idea-to-app-store-building-my-first-ios-app-with-react-native-1ej7</guid>
      <description>&lt;p&gt;I recently got my first iPhone app accepted into the Apple App Store. It is quite exciting to be able to have a product i’ve been working on by myself now available for a whole bunch of people to download. I tried to use a structured approach for the whole app creation/release process and I’ve outline that process in this article.&lt;/p&gt;

&lt;h4&gt;
  
  
  Motivation
&lt;/h4&gt;

&lt;p&gt;Why did I want to build an iOS app in the first place? Well, I like &lt;strong&gt;building out things that could be of use to myself and others&lt;/strong&gt;. Creating an app downloadable from the App Store makes it very easy for others to get the app on their phone and start using it. I have a bit of experience working with React Native at one of my previous jobs, so I was confident I could build the app myself.&lt;/p&gt;

&lt;p&gt;There is also the &lt;strong&gt;possibility for me to generate some passive income with iOS apps&lt;/strong&gt; , if I choose to monetize the app. I realize that the majority of apps in the app store make very little, so this is by no means my primary objective.&lt;/p&gt;

&lt;h4&gt;
  
  
  App Idea
&lt;/h4&gt;

&lt;p&gt;I wanted to &lt;strong&gt;build an app that I would want to use&lt;/strong&gt; , but that others would also want to use. I also, didn’t want to create something that already exists since I wanted to provide a unique solution to a problem. A lot of developers create games for the App Store, but I did not want to do that since I don’t play games on my iPhone and I find that games generally don’t positively impact a person when they play them.&lt;/p&gt;

&lt;p&gt;I’m someone that’s interested in keeping up-to-date with the latest in health, nutrition, and performance, and I’ve noticed a dieting trend called the &lt;a href="https://meat.health/knowledge-base/carnivore-diet-what-to-eat/"&gt;&lt;strong&gt;carnivore diet&lt;/strong&gt;&lt;/a&gt;, that a lot of people have been benefiting from. Out of curiosity, I decided to try the diet, and I quite enjoy it, so I’ve stuck with it so far. The diet only allows for meat products to be eaten.&lt;/p&gt;

&lt;p&gt;Since the carnivore diet is something that is a fairly recent phenomena, there weren’t any apps catered towards the diet and so I thought that might be a good void to fill. I got the &lt;strong&gt;idea of creating a food journalling app that would only allow for the addition of meat as food entries&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LgGJGlIm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AlIPi2H6AMr_mivY0AeR9Ww.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LgGJGlIm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AlIPi2H6AMr_mivY0AeR9Ww.jpeg" alt=""&gt;&lt;/a&gt;I decided to go ahead and create a meat journaling app for the carnivore diet (Photo by &lt;a href="https://unsplash.com/photos/DVRXFIH42d0?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jez Timms&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/meat?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Planning
&lt;/h4&gt;

&lt;p&gt;Once I decided what my iOS app would be about, I &lt;strong&gt;wrote a summary of what I wanted the app to do&lt;/strong&gt; so that I could keep it in mind while looking at features to add. Here’s what I came up with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An application to record entries of the meat eaten during the day. Targeted towards those following a carnivore diet. The app is simple and doesn’t include calories because people on the carnivore diet just eat until they are full. The app is a way to journal the amount of food eaten. A simple app with no extra fluff.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notice the emphasis I put on &lt;strong&gt;keeping the app simple&lt;/strong&gt;. Since this was my first mobile app, I wanted to make sure I didn’t make things too complicated for myself. Had I envisioned a feature-rich application, I know I would likely get discouraged and potentially give up on the entire project.&lt;/p&gt;

&lt;p&gt;Once I had a better idea of what I wanted to build, I started to list out the features I’d like to have in the app. I categorized things under V1 and V2, where V1 are features that should be part of the first version of the app and V2 would be features that would be cool to have in a future release.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mxgyPUDY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ae7ifGX_eSVUw1873OPBpzg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mxgyPUDY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2Ae7ifGX_eSVUw1873OPBpzg.png" alt=""&gt;&lt;/a&gt;The list of features I planned to have in the app for the first and second versions of the app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Design
&lt;/h4&gt;

&lt;p&gt;I care greatly for the user interface of applications as I believe it makes an application more enjoyable to use when the application looks good. For my application, I made sure to &lt;strong&gt;look at the design of other mobile apps for inspiration&lt;/strong&gt; on how I wanted my app to look. I collected screenshots of some apps I had on my phone as well as designs I found on &lt;a href="https://dribbble.com/"&gt;dribbble&lt;/a&gt;, and combined them all into a document. In the document, I made notes on the UI elements I liked and how a similar design might fit in with my app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Crhc29pS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADCexBJyyI0Bex7kmei8dvQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Crhc29pS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2ADCexBJyyI0Bex7kmei8dvQ.png" alt=""&gt;&lt;/a&gt;Annotated design images I compiled related to other mobile app user interfaces.&lt;/p&gt;

&lt;p&gt;After I had gathered some inspiration for the UI, I &lt;strong&gt;sketched out wireframes&lt;/strong&gt; for the screens I would need in the app. I did this by hand and then uploaded images of the sketches to &lt;a href="https://www.figma.com"&gt;Figma&lt;/a&gt;, the design app I use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kShZnPxQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AgYFe5ku0QjZ2sgv_HSQJBA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kShZnPxQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AgYFe5ku0QjZ2sgv_HSQJBA.png" alt=""&gt;&lt;/a&gt;The hand drawn wireframes for the screens in the app.&lt;/p&gt;

&lt;p&gt;Next up, I started building out high fidelity designs for the application. I did this all in Figma, and you can actually &lt;a href="https://www.figma.com/file/FuctAJdJ15WcqL0vw7wdYM5U/Meat-Journal?node-id=0%3A1"&gt;view the designs for yourself&lt;/a&gt;. I took all the icons from &lt;a href="https://www.flaticon.com/"&gt;FlatIcon&lt;/a&gt; and made sure to pay for the rights to use them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wh8suUUs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AiiE6oRAhc32bQvBNOXb17g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wh8suUUs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2AiiE6oRAhc32bQvBNOXb17g.png" alt=""&gt;&lt;/a&gt;Designs for each screen of the app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Development
&lt;/h4&gt;

&lt;p&gt;I decided to &lt;strong&gt;use React Native for the app&lt;/strong&gt; as I already had experience with it and did not want to learn a new programming language. I also decided I would &lt;strong&gt;only focus on developing for iOS&lt;/strong&gt; , even though React Native also allows you to build for Android. The decision to only focus on iOS is because making everything work exactly as intended on both iOS and Android takes a lot of work. Just because something works on iOS, doesn’t mean it will work on Android. Also, since I own an iPhone and not an Android it made sense to develop on iOS as I could test the app in both a simulator and physical device.&lt;/p&gt;

&lt;p&gt;I used a &lt;a href="https://github.com/infinitered/ignite-ir-boilerplate-bowser"&gt;&lt;strong&gt;React Native boilerplate&lt;/strong&gt;&lt;/a&gt; to quickly get up and running with the app development process. The boilerplate includes &lt;a href="https://www.typescriptlang.org/"&gt;&lt;strong&gt;TypeScript&lt;/strong&gt;&lt;/a&gt; &lt;strong&gt;and&lt;/strong&gt; &lt;a href="https://github.com/mobxjs/mobx"&gt;&lt;strong&gt;MobX&lt;/strong&gt;&lt;/a&gt;, which was really nice to work with. I had never used MobX prior to this project, but I really enjoyed using it to manage the global application state.&lt;/p&gt;

&lt;p&gt;I also setup the project with &lt;strong&gt;continuous integration/deployment with&lt;/strong&gt; &lt;a href="https://visualstudio.microsoft.com/app-center/"&gt;&lt;strong&gt;Visual Studio App Centre&lt;/strong&gt;&lt;/a&gt; so that every commit I made to my master branch would build the app and deploy it to Itunes Connect. Itunes Connect is where you can submit your app to the App Store as well as conduct using testing with &lt;a href="https://testflight.apple.com/"&gt;TestFlight&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I chose Visual Studio App Centre for the CI/CD of the project because their free tier was able to accommodate all of my needs with 240 minutes of build time per month with a max build time of 30 minutes per build. I wanted to use &lt;a href="https://circleci.com"&gt;Circle CI&lt;/a&gt;, but their free plan doesn’t allow for builds on MacOS machines, which is required for iOS. I also considered using &lt;a href="https://www.bitrise.io/"&gt;Bitrise&lt;/a&gt; since their UI/UX is really nice, but their max build time is 10 minutes per build and my builds were taking just over 10 minutes to complete.&lt;/p&gt;

&lt;h4&gt;
  
  
  User Testing
&lt;/h4&gt;

&lt;p&gt;Apple has their own user testing app called &lt;strong&gt;TestFlight&lt;/strong&gt; , which allows you to invite others to download and test an app before it gets released to the app store. I didn’t really have a good pool of trustworthy and interested people to test my app, but I did manage to get two of my friends to download my app through TestFlight. &lt;strong&gt;User testing of my app wasn’t really a priority for me as I did not have high expectations for the app.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Where I did end up &lt;strong&gt;getting a lot of feedback for my app was at a local UI/UX feedback meetup&lt;/strong&gt; I attended. I presented my app to a crowd of people who then provided feedback on how the app could be improved along with potential features I might want to add to the app. A lot of people were interested in the app, but I think it’s mainly because the carnivore diet seems so strange.&lt;/p&gt;

&lt;h4&gt;
  
  
  App Store Submission
&lt;/h4&gt;

&lt;p&gt;Before submitting to the app store, I made sure to read the &lt;a href="https://developer.apple.com/app-store/review/guidelines/"&gt;App Store Review Guidelines&lt;/a&gt; to make sure I didn’t miss anything that I should have done. There is a section of the submission form where you can include notes for the App Reviewers, and &lt;strong&gt;I made sure to leave a detailed description of what exactly the app should be able to do&lt;/strong&gt;. I’ve heard that this gives the Apple reviewers more confidence in your app and reduces the likelihood of your app being rejected.&lt;/p&gt;

&lt;p&gt;Also, I made sure to &lt;strong&gt;put effort into the screenshots I submitted with the app&lt;/strong&gt; , as those act as the initial impression of the app for those viewing the app in the App Store. I followed a typically design trend for the screenshots, where you include a screenshot of the app inside of the frame of an iPhone, with an accompanying short description.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lHhdlKPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A1sKcXVPeC1TOi6CVG01-jA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lHhdlKPq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A1sKcXVPeC1TOi6CVG01-jA.png" alt=""&gt;&lt;/a&gt;App screenshots I submitted along with my app.&lt;/p&gt;

&lt;p&gt;After I submitted my app for approval, I got an email less than 24 hours later saying that my app was approved, and a few hours later my app could be found in the App Store!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gwflTa_y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A0clpoo3TLGidQU4MOrpkDA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gwflTa_y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1024/1%2A0clpoo3TLGidQU4MOrpkDA.png" alt=""&gt;&lt;/a&gt;The MeatJournal app &lt;a href="https://itunes.apple.com/ca/app/meatjournal-carnivore-diet/id1438311847?mt=8"&gt;in the App Store&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;p&gt;From idea to release, the &lt;strong&gt;entire process took me a month&lt;/strong&gt;. Also, in terms of cost, I spent $136 CAD for the Apple Developer License and $15 CAD for the rights of the icons I used in the app. So in total, &lt;strong&gt;I spent $151 CAD (approx. $117 USD) on the app&lt;/strong&gt;. The Apple Developer License is good for 1 year, after which I would have to renew the license.&lt;/p&gt;

&lt;h4&gt;
  
  
  What’s Next
&lt;/h4&gt;

&lt;p&gt;I’ll continue using the app myself and see if there are other features I want to add to the app. I’ll monitor the number of downloads of the app and gather any feedback from users to see if it’s worth investing more time into further developing the app. I quite enjoyed the entire experience so I may even try to develop more apps for the app store.&lt;/p&gt;

</description>
      <category>ios</category>
      <category>passiveincome</category>
      <category>appstore</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Learning the Granular Details of a Programming Language?</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Sat, 20 Oct 2018 00:32:21 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/learning-the-granular-details-of-a-programming-language-pln</link>
      <guid>https://forem.com/robertcoopercode/learning-the-granular-details-of-a-programming-language-pln</guid>
      <description>&lt;p&gt;I'm currently reading "JavaScript: The Definitive Guide" and it's a mighty long book because it basically covers EVERYTHING related to JavaScript. This has got me wondering: Am I wasting my time by learning the granular parts of the JavaScript language?&lt;/p&gt;

&lt;p&gt;For example, JavaScript has this concept of a positive zero (&lt;code&gt;0&lt;/code&gt;) and a negative zero (&lt;code&gt;-0&lt;/code&gt;). Both values are equal in JavaScript, except when used with a divisor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;positiveZero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;negativeZero&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;positiveZero&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;negativeZero&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; true&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;postiveZero&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;negativeZero&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt; false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's be real, what are the odds of me remember such odd behaviour and what are the odds of that ever being useful while working with JavaScript?&lt;/p&gt;

&lt;p&gt;What do people think? It's it worth spending time learning such obscure parts of the language. If not, is it worth reading books that go into the real deep parts of a language?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Moving Away From Medium for Publishing Content?</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Fri, 19 Oct 2018 23:42:17 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/moving-away-from-medium-for-publishing-content-5df</link>
      <guid>https://forem.com/robertcoopercode/moving-away-from-medium-for-publishing-content-5df</guid>
      <description>&lt;p&gt;Are people starting to migrate towards platforms other than Medium for their blog posts (especially programming/developer related)? I'm thinking of no longer posting to Medium since there seems to be some benefits of having my content elsewhere. Here are some of the pros and cons I see:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lots of eyes on your post if they are part of a popular publication&lt;/li&gt;
&lt;li&gt;Cool analytics related to your posts&lt;/li&gt;
&lt;li&gt;Nice editor that auto-saves as you compose a post&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Syntax highlighting does not exist (brutal for technical programming articles)&lt;/li&gt;
&lt;li&gt;Comment system is weird (each comment is considered a "story")&lt;/li&gt;
&lt;li&gt;Low engagement with audience (compared with Dev.to)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone have thoughts on this topic?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>writing</category>
    </item>
    <item>
      <title>Should the Quality of GitHub Projects Be Evaluated by Their Star Count?</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Sun, 14 Oct 2018 04:28:22 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/should-the-quality-of-github-projects-be-evaluated-by-their-starcount-dp5</link>
      <guid>https://forem.com/robertcoopercode/should-the-quality-of-github-projects-be-evaluated-by-their-starcount-dp5</guid>
      <description>&lt;p&gt;GitHub doesn't show you many statistics related to a repository, aside from a repository's star count. When evaluating a repository on GitHub, I often find myself giving a lot of weight towards how many stars the repository has gained.&lt;/p&gt;

&lt;p&gt;Repository owners especially love it when they receive a lot of GitHub stars as it provides them with a sense of accomplishment. There are articles written on &lt;a href="https://medium.freecodecamp.org/how-to-get-up-to-3500-github-stars-in-one-week-339102b62a8f"&gt;how developers can get more GitHub stars&lt;/a&gt; for their repositories, using tips such as writing an attractive README and even using paid advertising to get more eyes on the repo.&lt;/p&gt;

&lt;p&gt;The other day I stumbled upon a set of guidelines for recruiters that are trying to hire developer talent. One of the recommendations was to look for developers who have repositories on GitHub with 100+ stars.&lt;/p&gt;

&lt;p&gt;Should we all be evaluating the quality of a GitHub repository based on its star count? Probably not, but it is an easy metric for people to look at. There are a ton of different factors that factor into a great GitHub project.&lt;/p&gt;




&lt;p&gt;Here are some things to look at when trying to evaluate the quality of a GitHub repository:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pull Requests&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seeing recently merged pull requests is a good sign that the project is actively being maintained and improved. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Issues&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Issues that are answered in a timely fashion by maintainers is usually a good sign. I wouldn't worry too much about the amount of issues in a repository, as large repositories are likely to have a bunch of issues. For example, at the time of writing, the VS Code repo has 3,925 issues, but their app is incredibly useful.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NPM downloads&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also look at the downloads a tool has in NPM to see how popular a project is within the community. There is a good article that talks about &lt;a href="https://zendev.com/2018/06/19/react-usage-beating-vue-angular.html"&gt;when Vue surpassed React&lt;/a&gt; in terms of GitHub stars, but React is still downloaded much more than Vue on NPM. If a project is highly downloaded from NPM, it means a lot of other projects rely on it so it hopefully has some good stable features you can take advantage of in your own projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a project has little to no documentation, it doesn't matter how good the project  is because you won't know how to use it. Having detailed and easily to understand documentation associated with a project is a good sign that the project can be used in all the ways described by their own documentation.&lt;/p&gt;




&lt;p&gt;Overall, don't just rely on how many stars a project has when trying to evaluate an open source project. A good tool could solve a very specific need for a niche audience, but have a low number of stars on GitHub since it isn't a trendy or popular tool.&lt;/p&gt;




&lt;p&gt;If you found this article consider following me on &lt;a href="https://twitter.com/RobertCooper_RC"&gt;Twitter&lt;/a&gt;, &lt;a href="https://github.com/robertcoopercode"&gt;Github&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/robert-cooper/"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>github</category>
    </item>
    <item>
      <title>Using Aliases to Speed Up Your Git Workflow</title>
      <dc:creator>Robert Cooper</dc:creator>
      <pubDate>Mon, 03 Sep 2018 00:43:08 +0000</pubDate>
      <link>https://forem.com/robertcoopercode/using-aliases-to-speed-up-your-git-workflow-2f5a</link>
      <guid>https://forem.com/robertcoopercode/using-aliases-to-speed-up-your-git-workflow-2f5a</guid>
      <description>&lt;p&gt;Leveraging aliases when working with git can help make you more efficient with using the popular version control system. Listed below are some of my absolute favourite and most used aliases when working on a project that uses git.&lt;/p&gt;

&lt;p&gt;It should be noted that when i'm talking about aliases, I mean &lt;a href="http://tldp.org/LDP/abs/html/aliases.html" rel="noopener noreferrer"&gt;bash/zsh aliases&lt;/a&gt; and not &lt;a href="https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases" rel="noopener noreferrer"&gt;git aliases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What's the difference? Bash/Zsh aliases are setup in a &lt;code&gt;.bashrc&lt;/code&gt; or &lt;code&gt;.zshrc&lt;/code&gt; file and allows you to assign a command to a shorthand version. For example, you could alias &lt;code&gt;git log&lt;/code&gt; to be &lt;code&gt;gl&lt;/code&gt;, which would save you a few characters of typing. Git aliases allow you to similarly assign a git command to a shorthand version, but you still have to type &lt;code&gt;git&lt;/code&gt; prior to the shorthand. For example, you could alias the &lt;code&gt;git log&lt;/code&gt; command to be &lt;code&gt;l&lt;/code&gt; and then you would invoke the command by typing &lt;code&gt;git l&lt;/code&gt;. All git aliases are set in a &lt;code&gt;.gitconfig&lt;/code&gt; file which is usually found in a computer's &lt;code&gt;HOME&lt;/code&gt; directory.&lt;/p&gt;




&lt;h2&gt;
  
  
  Adding and Amending Commits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gaa&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;-A&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adds all changes to staging.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gcm&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creates a new commit with all staged files and uses the given message as the commit's message.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcm &lt;span class="s2"&gt;"This is my commit message describing the changes"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gcma&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adds all files to staging and makes a commit using the given message as the commit's message.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcam &lt;span class="s2"&gt;"This is another commit message!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gca&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;--no-edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Moves the currently saved files into the previous commit message. The &lt;code&gt;--no-edit&lt;/code&gt; flag is passed to &lt;code&gt;git commit --amend&lt;/code&gt; to keep the previous commit message (this is usually the case).&lt;/p&gt;

&lt;p&gt;If the previous commit message should be changed, I've aliased &lt;code&gt;git commit --amend --no-edit&lt;/code&gt; to &lt;code&gt;gcae&lt;/code&gt;. It does the same as &lt;code&gt;gca&lt;/code&gt;, but it opens up the git editor to edit the previous commit's message. In my case, I've setup &lt;code&gt;VS Code&lt;/code&gt; to be my default git editor since i'm not proficient with VIM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fnggwfw3f296xawe161ry.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fnggwfw3f296xawe161ry.png" alt="Previous commit message displayed in VS Code with instructions on how to change the commit message." width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gcaa&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nt"&gt;--all&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;--amend&lt;/span&gt; &lt;span class="nt"&gt;--no-edit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command is useful to use if some changes that have been made should be a part of the previous commit. It will add all newly modified files to staging and then it will &lt;code&gt;amend&lt;/code&gt; the previous commit with those changes. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gnope&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Removes all the changes detected by Git.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gwait&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset HEAD
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unstages everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gundo&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git reset &lt;span class="nt"&gt;--soft&lt;/span&gt; HEAD^
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Undoes the last commit and moves the files in the commit to staging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading history
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gl&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git log &lt;span class="nt"&gt;--graph&lt;/span&gt; &lt;span class="nt"&gt;--pretty&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'\''%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&amp;lt;%an&amp;gt;%Creset'&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;' --abbrev-commit
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logs previous commits in a concise manner. The argument passed to &lt;code&gt;--pretty&lt;/code&gt; is defining the information that should get displayed for each commit (i.e. commit hash, branch name, commit message, date of commit, and author). Definitely wouldn't want to type this out every time!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gco&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Allows to switch between branches.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gco other-branch-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pushing &amp;amp; Pulling To/From Remote
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gps&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Updates the remote.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gpsf&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git push &lt;span class="nt"&gt;--force-with-lease&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overrides the remote branch with the local branch if no one else has commited to the remote. It is considered to be a safer approach than using &lt;code&gt;git push --force&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;gpl&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull &lt;span class="nt"&gt;--rebase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fetch updates from the remote and rebase the local branch with the upstream branch. This avoids any merge commits that may occur when using &lt;code&gt;git pull&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebasing
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;grb&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rebases the current branch with another branch.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grb origin/master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;grn&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;(shell command)&lt;/em&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grn&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; HEAD~&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is actually a &lt;a href="http://zsh.sourceforge.net/Intro/intro_4.html" rel="noopener noreferrer"&gt;shell command&lt;/a&gt; which allows for variables to be passed in as arguments. The &lt;code&gt;$1&lt;/code&gt; is a placeholder for an argument that gets passed to the &lt;code&gt;grn&lt;/code&gt; function. This function accepts &lt;code&gt;N&lt;/code&gt; as an argument, where &lt;code&gt;N&lt;/code&gt; is the number of commits to perform an interactive rebase on.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F17gh4q40sc5rpoflo62e.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F17gh4q40sc5rpoflo62e.gif" alt="Example usage of the grn shell command" width="2066" height="1398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;grbic&lt;/code&gt;&lt;/strong&gt; &lt;em&gt;(shell command)&lt;/em&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;grbic&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; git rebase &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Accepts a commit hash as an argument and performs an interactive rebase back to the passed commit hash.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fxpkqr1ggby5roevvbkul.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fxpkqr1ggby5roevvbkul.gif" alt="Example usage of grbic shell command" width="2066" height="1398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;grba&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase &lt;span class="nt"&gt;--abort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aborts an interactive rebase and restores the git state to the moment the &lt;code&gt;git rebase&lt;/code&gt; command was run.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;grbc&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git rebase &lt;span class="nt"&gt;--continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Continues an interactive rebase after conflicts on a commit have been resolved.&lt;/p&gt;




&lt;p&gt;Ok, I know that was a lot of aliases, so sorry for rambling on about them. I would encourage others to start aliases more often to speed up their development. Let me know if any of those were helpful or if you've got some favourite aliases you'd like to share.&lt;/p&gt;




&lt;p&gt;If you found this article consider following me on &lt;a href="https://twitter.com/RobertCooper_RC" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;, &lt;a href="https://github.com/robertcoopercode" rel="noopener noreferrer"&gt;Github&lt;/a&gt;, or &lt;a href="https://www.linkedin.com/in/robert-cooper/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
    </item>
  </channel>
</rss>
