What is Docker?
Docker is a container technology: A tool for creating and managing containers.
Container is a standardized unit of software. A
package of code and a set of dependencies, required to run that code.
The same container always yields the exact same
application and execution behaviour, no matter where or by whom it might be executed.
Why Containers?
We often have different environments for development and production. Also, if multiple developers are working on a same project, then it is common to forget about some dependency or environment variable or installing different version of a dependency, etc. Not just while development, it is also possible that this issue comes in production. You might have also heard the phrase, ***“It works on my machine!”***, a lot. To avoid all these kinds of conflicts, containers were born.
Virtual Machines vs Docker Containers
Docker Containers are kind of like Virtual machines, but a lot lot light weight. Virtual machines have a lot of overhead like GUI, RAM usage, ROM Usage, Power consumption, and a lot more CPU consumption to run a single machine. A rough comparison, on a standard machine, we can run 2-3 virtual machines simultaneously, or we could run around 10-30 different containers simultaneously.
Docker Images
Images are the actual bundled code and dependencies and can be used as Template for the container. For reference, you can think of Docker image as a Virtual machine’s image that we use to install a Virtual Machine.
Key takeaways:
- Images do not run themselves, instead, they can be executed as containers.
- Images are either pre-built (e.g. official images you find on DockerHub) or you build your own images by defining a Dockerfile.
Installing Docker
There is no standard way to install Docker on Linux, Windows, or Mac and even different versions of the Operating Systems.
So, please follow this link to
install docker on your machine and come back once you are sure that docker is configured and running correctly.
To check if docker is configured and running,
$ docker run hello-world
If your system doesn’t meet the docker requirements, then you can use this
Online Playground to learn docker.
Dockerfile
A file that is used to build a Docker image.
Example: Creating a Dockerfile for a mongodb from scratch
# step 1: Setup OS from a base image
FROM alpine
# step 2: Install software
RUN echo 'http://dl-cdn.alpinelinux.org/alpine/v3.6/main' >> /etc/apk/repositories
RUN echo 'http://dl-cdn.alpinelinux.org/alpine/v3.6/community' >> /etc/apk/repositories
RUN apk update
RUN apk add mongodb=3.4.4-r0
# step 2.5: Configure software
# basically, mkdir -p /data/db, but this is persistent.
# We can attach to this volume from different container as well.
# https://stackoverflow.com/questions/34809646/what-is-the-purpose-of-volume-in-dockerfile
VOLUME [ "/data/db" ]
# set the current working directory to /data
WORKDIR /data
# expose
EXPOSE 27017
# step 3: Set default commands
CMD [ "mongod" ]
# Docker ignore
# Create a .dockerignore file in the same directory to add files and directories to that.
# These files won't be considered by docker for any purpose.
Sample Dockerfile
for a Node.js app:
# Base image for our image (alpine versions should
# be used to reduce the image size)
FROM node:14
# Set the working directory for our app.
# Default is the root directory.
WORKDIR /app
# We do this first because docker does
# caching at all layers and if docker
# detects that the layer has not changed,
# then it uses artifacts from the cache
# which was created during the previous run.
COPY package.json /app
# Install all the dependencies.
# RUN command runs the specified instructions
# when creating the image.
RUN npm install
# When executing a command in the running
# container with the help of `docker exec`,
# we can skip the prefix of the commands.
# For eg. `npm init` becomes `init` and
# `npm install express` becomes `install express`.
# Check the [Exec](#exec) section to learn more.
ENTRYPOINT [ "npm" ]
# Copy all the project files to the working # directory in our image.
COPY . /app
# Our app is running on port 3030. This
# exposes the container's 3030 port to the
# outside world
EXPOSE 3030
# A command that will run our server file.
# CMD is used when we want the command to
# run when the container is running and
# not while creating the image.
# A Dockerfile should have exactly one CMD command.
CMD [ "node", "app.js" ]
Key Docker commands
Build an image
$ docker build .
# `.` is the directory that contains the
# Dockerfile.
Options:
-t NAME:TAG
: Assign aNAME
and a
TAG
to an image
Examples:
docker build -t username/friendlyhello:tag .
Run a Docker image
$ docker run <IMAGE-NAME>
Options:
--name NAME
: Assign aNAME
to the
container.-d
: Run the container in detached
mode.-it
: Run the container in interactive
mode and enable TTY.--rm
: Automatically remove the
container when it’s stopped.
Tag an image
$ docker tag <image> username/repository:tag
List all locally stored images
$ docker image ls
Remove an image
$ docker image rm <IMAGE-ID>
$ docker image rm <IMAGE-NAME>
Remove all images
$ docker image prune
# Removes all dangling images (untagged images)
$ docker image rm $(docker image ls -a -q)
# Remove all images
Options:
-a
: Remove all locally stored images
Start a container
$ docker start <CONTAINER-ID>
$ docker start <CONTAINER-NAME>
Stop a container
$ docker stop <CONTAINER-ID>
$ docker stop <CONTAINER-NAME>
$ docker container kill <CONTAINER-ID>
# Force shutdown of the specified container
Stop all containers
$ docker container stop $(docker container ls -a -q)
List all containers
$ docker container ls
Options:
-a
: List all containers - including
stopped ones.
Remove container
$ docker container rm <CONTAINER-ID>
$ docker container rm <CONTAINER-NAME>
Remove all containers
$ docker container prune
# Remove all stopped containers
$ docker container rm $(docker container ls -a -q)
# remove all containers
Push image to a registry
$ docker push IMAGE
# Push an image to DockerHub (or another # registry) - the image name/tag must # include the repository name/ url
Pull an image from the registry
$ docker pull IMAGE
# this is done automatically if you just # `docker run IMAGE` and the image wasn't # pulled before.
Ignore files when copying
Create a .dockerignore
file. It is similar to the
.gitignore
file. When we run COPY . .
in our Dockerfile, docker won’t copy files mentioned in the .dockerignore
file.
Sample .dockerignore
node_modules/
Dockerfile
.git/
.env
Environment variables
Using environment variables
EXPOSE $PORT
Setting Environment variables In a Dockerfile
ENV PORT 80
Setting Environment variables In CLI
$ docker run -d -p 3000:4242 -e PORT=4242 some-image
Read Environment Variables from a .env file
$ docker run -d -p 3000:4242 --env-file ./.env some-image
Build Arguments
Arguments are build time arguments that can be used
inside the Dockerfile.
ARG DEFAULT_PORT=4224
ENV PORT $DEFAULT_PORT
Usage:
$ docker build --build-arg DEFAULT_PORT=9999 .
# port will be 9999
$ docker build .
# port will be 4224
Exec
We can use this command to run any command inside any
running container.
$ docker exec -it <container-name> <command>
# eg
$ docker exec -it my_running_node npm init
# If `ENTRYPOINT` was set in Dockerfile
# ENTRYPOINT ["npm"], then we can omit the
# initial command
$ docker exec -it my_running_node init
# runs `npm init`
$ docker exec -it my_running_node install express
# runs `npm install express`
I hope this post helped you understand basics of
docker. Feel free to share your thoughts in the
comments section below.
Comments
Post a Comment