ArkarDev

Getting Started with Docker for web dev

Jun 22, 2023Arkar Kaung Myat
Docker

A beginner's guide to using Docker for front-end development: everything you need to know to get started.

In this article, I'll explain what Docker is and how you can start using it in your daily work.

Docker is a tool that helps you make applications quickly. It works by putting different parts of your application, like databases and servers, into separate boxes called "containers". This makes it easy to create a place where you can build and test your application.

Using Docker to set up components saves time compared to setting up each component manually on your local machine. Docker also allows you to switch easily between different versions of these components, which is helpful when testing changes or fixing issues.

With Docker, you can create a container that has all the necessary tools and dependencies for your project, and then you can also share that container with other developers on your team. This ensures that everyone is working in the same environment and reduces the time needed to set up new environments.

This article is gonna be a bit more straightforward and more like a guide for you to get started with docker. If you want more on what containers are you can check out the official Docker documentation and many great resources out there.

However, there are a few terms that I will be using throughout this article.

# Docker Client

The Docker command is used to control most of the Docker workflow and communicate with remote Docker servers.

# Docker Server

A Docker Server is a program that helps you manage containers, images, and other resources in Docker. It is installed on your computer and lets you create, run, and manage containers. When you want to create or manage containers, you use a Docker Client to communicate with the Docker Server.

# Docker Images

Docker images consist of one or more filesystem layers and some important metadata that represent all the files required to run a Dockerized application. A single Docker image can be copied to numerous hosts. A container will typically have both a name and a tag. The tag is generally used to identify a particular release of an image.

# Docker Containers

A Docker container is a Linux container that has been instantiated from a Docker image. A specific container can only exist once; however, you can easily create multiple containers from the same image.

# Install docker on your local machine

To use it, we first need to install it on our computer. This is a quick and simple process. You can find detailed installation guides for Windows, macOS, and Linux on the official Docker website.

Install Docker on your local machine .

After installing Docker on your machine, test it by running docker -v. If the output looks like this, everything should be working perfectly.

❯ docker -v
Docker version 24.0.2, build cb74dfcd85

# Hello world example

Now that Docker is installed, let's try running our first Docker container. The "Hello world" example is a simple way to do this. Open up a terminal window and enter the following command:

❯ docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
719385e32844: Already exists
Digest: sha256:c2e23624975516c7e27b1b25be3682a8c6c4c0cea011b791ce98aa423b5040a0
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

Docker will pull the "hello-world" image from the Docker Hub repository and start a new container. The container will print a "Hello from Docker!" message to your terminal.

What happened is

The docker run hello-world command makes the computer run the "hello-world" image from Docker Hub. Docker gets the image from the repository and starts a new container. Then the container prints Hello from Docker! to your terminal. This says that Docker is installed and working right.

# Docker Hub

Docker Hub is similar to Github but for Docker images. It provides a public registry where you can find pre-made images of popular applications such as MySQL, PostgreSQL, and Nginx that can be used in your projects. Other users can also upload their own images, and you can share your own images with the Docker community.

To use Docker Hub, create a free account, search for images you want to use, download them, and use them to create a new container on your computer. Docker Hub also lets you create your own repositories and upload your own images, which is useful if you've made a custom image for a specific project and want to share it with others.

# Interacting with Docker Images

One of the most important things you can do with Docker is to use pre-existing images to build your containers. Docker Hub is a public registry that hosts a large number of pre-made images of popular applications like MySQL, PostgreSQL, and Nginx that can be used in your projects. Docker Hub also allows users to upload their own images, which can then be shared with the Docker community.

To use an image from Docker Hub, you need to pull it to your local machine. For example, if you want to use the latest version of Ubuntu, you can pull it from Docker Hub by running the following command:

❯ docker pull ubuntu:latest

This will download the latest version of the Ubuntu image to your local machine. You can now use this image to create a new container:

❯ docker run -it ubuntu:latest bash

The docker run command starts a new container based on the Ubuntu image. The -it flag tells Docker to allocate a pseudo-TTY and keep it open, and the bash command specifies that we want to run a bash shell inside the container.

Once you've started the container, you can interact with it just like you would with a regular Ubuntu installation. For example, you can install new packages using the apt-get command:

root@<container-id>:/# apt-get update
root@<container-id>:/# apt-get install -y curl

When you're done working with the container, you can exit the shell by running the exit command:

root@<container-id>:/# exit

This will terminate the container and return you to your local machine's shell.

Try running these commands in your terminal.

docker run  ubuntu:latest ls
docker run  ubuntu:latest cat /etc/issue

To see a list of the Docker images you've downloaded to your computer, use the docker images command.

❯ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              latest              2c047404e52d        4 weeks ago         72.9MB
hello-world         latest              bf756fb1ae65        8 months ago        13.3kB

In this example, we got the latest version of the Ubuntu and hello-world images. The REPOSITORY column shows the image name, the TAG column shows the image version, the IMAGE ID column shows a unique identifier for the image, the CREATED column shows when the image was created, and the SIZE column shows the image's size on the disk.

Check out Docker Cli Reference

For example, to remove images you don't need anymore, use the docker rmi command. For instance, to remove the "hello-world" image from your local machine, run the following command:

❯ docker rmi hello-world

This will remove the "hello-world" image from your local machine and free up disk space.

# Creating docker images

This blog post will cover how to create your own Docker image for json-server and use it in your front-end applications. Here is an example of a json-server server. You can look at their documentation for more.

const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router('db.json')
const middlewares = jsonServer.defaults()

server.use(middlewares)
server.use(router)
server.listen(1337, () => {
  console.log('JSON Server is running')
})

And then create a Dockerfile in your project root and add a config like this

FROM node:latest
USER node

WORKDIR /home/node/code
COPY --chown=node:node package*.json ./
RUN npm install 

COPY . .

CMD ["node", "index.js"]

In the above code,

  1. Use FROM to specify the base image for the new image, using the latest Node.js image.
  2. Use USER to choose the user to run the app as, selecting the node user from the Node.js image.
  3. Set the working directory for the application with WORKDIR.
  4. Copy the package*.json file to the working directory with COPY.
  5. Install dependencies specified in package*.json with RUN and npm install.
  6. Copy all files in the current local directory to the working directory with a second COPY command.
  7. The CMD instruction in the Dockerfile specifies the command that should be run when the container starts. In this case, the index.js file will be run with Node.js when the container starts. When you run the container, Docker will start a new process with the specified command inside the container.

That's it! You've now created and run your own Docker image for a Node.js application.

docker build -t json-server .

This will build a new Docker image with the tag json-server.

To run a container based on the new image, you can use the docker run command:

docker run -p 1337:1337 json-server

This will start a new container based on the json-server image that we just created and map port 3000 on your local machine to port 3000 in the container. And as you will see your docker container will be up and running.

To see what containers are currently running:

  • Use the docker ps command in your terminal.
  • This will display a list of all running containers, including their ID, image, status, and other details.

❯ docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED          STATUS          PORTS                                       NAMES
4cc659545a99   json-server   "docker-entrypoint.s…"   28 seconds ago   Up 27 seconds   0.0.0.0:1337->1337/tcp, :::1337->1337/tcp   beautiful_spence

This will show you what is happening and help you solve any problems you might have.

To access a Docker container from your local machine, you need to publish its ports. Since containers are isolated from the host system, their ports need to be published to the host in order to be accessed.

Once the port is published, you can access the container's application by visiting http://localhost:<port> in your web browser.

❯ docker run -p 3000:1337 my-container

Read More on Docker’s CLI reference

# Interacting with multiple containers

Suppose you're making a web app with a blazingly fast svelte front-end, an Express API, and a PostgreSQL database. It can be hard to run all three on your computer, especially if you're working with other developers who have different setups.

When using Docker, you might need to run multiple containers for different parts of your app. You can use Docker Compose for that.

More on Docker Compose

# Svelte App

Here is a simple SvelteKit server that uses data from our previous json-server container.

FROM node:latest
WORKDIR /app
COPY package.json /app/
RUN npm install
COPY . /app/
RUN npm run build
EXPOSE 3000 
CMD ["node", "build/index.js"]

To work our containers together we can create a svelte compose file for that

To work the containers together, you can create a docker-compose.yml file. In this file, you can define the different services (i.e., containers) that you want to use, along with any configuration options that they need.

For example, if you're working on a web app with a Svelte front-end, an Express API, and a PostgreSQL database, you could define the following services:

version: '3'
services:
  web: 
    build: ./json-web/
    ports :
      - "3000:3000"
    depends_on:
      - api
  api:
    build: ./json-server/ 
    ports:
      - "1337:1337"

In this example, we define three services:

  • web: This service is based on a Svelte front-end that is built from the ./web directory. It is exposed on port 3000, and it depends on the api service.
  • api: This service is based on an Express API that is built from the ./api directory. It is exposed on port 1337.

With this docker-compose.yml file, you can start all three services at once by running the following command in the same directory as the file:

❯ docker-compose up

Docker Compose will build the necessary Docker images and start the services in the correct order. You can then access the Svelte front-end at http://localhost:3000 and the Express API at http://localhost:8080 .

[+] Building 0.0s (0/0)
[+] Running 2/0
 ✔ Container docker-api-1  Created                                       0.0s
 ✔ Container docker-web-1  Created                                       0.0s
Attaching to docker-api-1, docker-web-1
docker-api-1  | JSON Server is running : http://localhost/1337
docker-web-1  | Listening on 0.0.0.0:3000

This is just a simple example, but Docker Compose can be used to orchestrate much more complex applications with multiple services and dependencies.

# Networks in docker

Docker containers are like mini virtual computers that are separate from the main computer they are running on. They each have their own space to store files and run programs, and they can communicate with other containers using a special network. This means that developers can test their software without worrying about it interfering with anything else on the computer. However, if you want containers on different computers to communicate with each other, you need to set up a new network.

❯ docker network create my-network

You can then run containers on this network by specifying the --network flag when you create them. For example, to run a container on the my-network network, run the following command:

❯ docker run --network my-network my-image

This will start a new container based on the my-image image and attach it to the my-network network. The container will be able to communicate with other containers on the same network, even if they are running on different hosts.

You can also inspect and manage networks using the docker network command. For example, to see a list of all networks on your system, run the following command:

❯ docker network ls

This will display a list of all networks on your system, including their names, drivers, and other details.

More on networking between container

Check out Repository for the example I did in this article.