LinuxNetworking

Learning Docker

Note: I just literally copy-pasted my personal note here, so some details might be missing. If anything confusing let's chat in the comments section.

Learning Resources

First Alpine Linux Containers

Summary

  • VM is hardware-abstraction but docker is application-abstraction concept.

Running your first container

docker container run hello-world
  • hello-world image was not present locally. So it will be pulled from Docker trusted registries which by default is DockerHub.
  • The Docker client (command we are using) contacted the Docker daemon.
  • The Docker daemon pulled the “hello-world” image from the Docker Hub.
  • Daemon is the background service running on the host that manages building, running and distributing Docker containers.
  • The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading.
  • The Docker daemon streamed that output to the Docker client, which sent it to your terminal.

Docker Images

docker image pull alpine

Alpine is a lightweight Linux distribution so it is quick to pull down and run. Only 8 MB build and needs minimum 130MB storage to install.

  • To see all the available images
docker image ls
  • Running the container
docker container run alpine /bin/sh

The docker ran an instance of the docker container and it ran the command /bin/sh and then exited. You did not supply any additional commands to /bin/sh so it just launched the shell, exited the shell, and then stopped the container.

  • Running the container interactively
docker container run -it alpine /bin/ash
  • Looking at all the docker containers inside the system
docker container ls -a

Container Isolation

Each container has a separate file system and runs in a different namespace; by default a container has no way of interacting with other containers, even those from the same image.

  • Starting the exited container again
docker container start <container ID>

You could also use first few characters of ID given that it is unique.

Tip: /bin/sh exits quietly but /bin/ash awaits for a command. So it wont die.

  • Executing command on that running container
docker container exec <container ID> ls
  • To stop the running container
docker stop <CONTAINER_ID> -t 1

Stop it after 1 seconds. Default is 10 seconds.

  • Deleting a container
docker rm <CONTAINER_ID>
  • Deleting a docker image
docker rmi <IMAGE_ID>

Remember: Before you can delete an image, you must delete all the containers using it.

Creating our own Docker Images

Often we will want to modify the existing images. add some libraries and programs inside then bundle it to form our custom image which can be used later. Two ways of doing:

Manually adding libraries and using commit method

Make changes in the recent running container, then you can exit. Now make an image out of this.

docker container commit CONTAINER_ID
docker image tag <IMAGE_ID> image_name
  • Running commands with our newly created image
docker container run image_name figlet hello

Using Dockerfile

  • With a Dockerfile we are supplying the instructions for building the image, rather than just the raw binary files.
  • If new version of package comes, then we manually need to update it and re-create our image in case of commit method. But in Dockerfile, we could mention the apt-get command so it makes updating the image easier.
Building node.js app with Dockerfile
  • Build a index.js example file.
var os = require("os");
var hostname = os.hostname();
console.log("hello from " + hostname);
  • And a docker file
FROM alpine
RUN apk update && apk add nodejs
COPY . /app
WORKDIR /app
CMD ["node","index.js"]
docker image build -t hello:v0.1 .
  • Start the container
docker container run hello:v0.1
  • Output
hello from 92d79b6de29f

Image Layers

  • What you see is the list of intermediate container images that were built along the way to creating your final Node.js app image.
  • This is a powerful concept because it means that if we need to make a change to our application, it may only affect a single layer!

Let’s make some modifications to the index.js file and again run the docker build command. This time hello:v0.2. See how it uses cache files to build the new image because update and nodejs packages haven’t changed. Since index.js changed, it will work from there.

Image Inspection

Lets inspect the layers of the apline image vs our hello image.

docker image inspect alpine [This gives everything about the image]
docker image inspect --format "{{ json .RootFS.Layers }}" alpine
docker image inspect --format "{{ json .RootFS.Layers }}" <IMAGE_ID>

Both alpine and hello are using the same base layer, which we know because they have the same sha256 hash.

Dockerizing Node.js application

How To Build a Node.js Application with Docker | DigitalOcean

Dockerizing a Node.js web app | Node.js

Dockerfile

FROM node:10-alpine
RUN mkdir -p /home/node/app/node_modules && chown -R node:node /home/node/app
WORKDIR /home/node/app
COPY package*.json ./
USER node
RUN npm install
COPY --chown=node:node . .
EXPOSE 3000
CMD [ "node", "./bin/www" ]

While I used node:alpine only, it gave error. node:lts-alpine worked.

.dockerignore

node_modules
npm-debug.log
Dockerfile
.dockerignore

Build your image

docker build -t app:v0.1 .
docker image ls

The image naming format is different if you want to upload it to registries (DockerHub).

Now lets start the container using this image.

docker run --name <memorable_name> -p 80:3000 -d app:v0.1
docker ps
  • d means run in background. -p maps port 80 in the host to port 3000 on the container.

If you need to go inside the container you can use the exec command:

docker exec -it <container id> /bin/bash

Problems + Solutions

Stuck at npm install phase. Can’t connect to npmjs website.

Fix Docker’s networking DNS config

Create /etc/docker/daemon.json file in the host machine.

{
    "dns": ["dns_server_of_host", "8.8.8.8"]
}

First it will contact the host’s default DNS server and 8.8.8.8 (Google) is used as a fallback.

sudo service docker restart

Kiran Dawadi

Founder of cybersecnerds.com. Cybersecurity professional with 3+ years experience in offensive web security, cloud security and building systems. I am a Linux envagelist and highly interested in source-code auditing. You will find me reading InfoSec blogs most of the time.

Subscribe
Notify of
guest

1 Comment
Inline Feedbacks
View all comments
Pandey Bikash
Pandey Bikash
2 years ago

GOOD !!