Docker is an open source containerization tool that manages isolated environments (containers).
Containers include all the tools and dependencies needed to run specific software.
The key difference between containerization and virtualization is that containers are lightweight and much faster to run than virtual machines.
Virtual machines require hardware virtualization (RAM, CPU, STORAGE, etc.) and a separate OS via a hypervisor.
Docker engine uses OS-level virtualization, sharing the host kernel to run and manage containers in isolation.
A container is an isolated running environment instantiated from an image by the Docker engine.
It can be started, stopped, and deleted. Developers use containers to package software and dependencies
to run on any target system and avoid the "it runs on my machine" problem.
A Docker image is a read-only template that packages all libraries and system dependencies needed to run specific software.
Think of it as a blueprint or snapshot for containers, since the Docker engine initializes containers from images.
The image does not change after a container is created from it.
Docker is mainly used by development teams to share consistent development environments.
All team members can share a Dockerfile that defines standard dependencies and packages.
This file is used to build images and then containers, ensuring new features work for everyone.
Docker is also popular for developing applications with microservices architecture, as each service can run in its own independent container.
- $ docker pull "image-name"
- $ docker image list or docker images
- $ docker run "image-name"
- $ docker ps
- $ docker start "name/id"
- $ docker stop "name/id"
- $ docker kill "name/id"
- $ docker rm "name/id"
- $ docker exec "name/id" 'a command'
- $ docker attach "name/id"
Fetch a Docker image from Docker Hub to your machine for container instantiation.
You can specify the source, but Docker Hub is the default.
List available Docker images on your machine.
Run a container from an image. Flags like --name "desired-name", --rm, and -it can be added.
List all running Docker containers. Add -a to see stopped ones.
Start an existing stopped container. Deleted containers cannot be retrieved.
Gracefully stop a running container and keep its state. It will be visible with docker ps -a.
Immediately and forcefully stop a running container. Use only as a last resort, as it may cause data loss.
Delete a specified container (not the image). The container must be stopped first.
Execute a command in a running container. For example, $ docker exec -it container bash opens an interactive shell.
Attach your terminal to a running container. Closing the terminal gracefully stops the container.
A Dockerfile is a plain text file that Docker uses to build container images.
The syntax is: INSTRUCTION argument.
Each instruction creates a read-only layer in the image. Layers are cached and reused by Docker.
Docker assigns a unique hash to each layer change and checks for cached layers when building images.
If a match is found, Docker reuses the cached layer; otherwise, it creates a new one.
- FROM <base image>:
- RUN <command:> args...
- CMD <command:>[args...]
- ENTRYPOINT <command:>[args...]
- ENV var=val
- COPY host-path container-path
- ADD 'src' 'dest'
this is a mandatory instruction that must be set before any other one, it is used to specify
which base image will be used to create your new image, it is fetched from an image registry
docker hub by default you may have a 'chicken and egg question' in mind and ask if each time i want to
make an image i should always use FROM to fetch a base image how did the first image was created ?
the answer is that The process for creating a foundational base image like debian, or alpine
is a manual they compress the minimal filesystem from the OS as a tar file and use it as the pulled base
image, you can also use FROM scratch so you will not use any image as your starting point, and then copy
the file system tar to your image directly.
is used to run programs that are needed or just desired to be
executed while creating the image, it can be used in two different ways :
1. RUN [arg1] [...] in this case the dockerd will relay on the default
base image shell to run the command.
2. RUN ["bin path", "arg1", ...] in this case dockerd will execute the command
directly without relaying on the shell.
is a way of specifying a default command that will
be used by the container, which means it will be the PID 1 for the container
and if it exits the container itself will stop, this command will usually be set
to a long running command such as a shell or a web server, whats important to
know is that this instruction doesn't have anything to do with the image creation
so it will not add a new layer but only be used a starting point when a container
is started form the image, this command can be overridden by the argument passed to
docker run, keep in mind that if ENTRYPOINT is used the CMD value will only be used
as a parameter for the command specified in ENTRYPOINT
is similar to CMD except that command-line arguments passed to docker run are used as
parameters for the ENTRYPOINT command, The ENTRYPOINT itself can be overridden using
the --entrypoint flag in docker run If both ENTRYPOINT and CMD are used
the CMD value will be used as extra arguments for the ENTRYPOINT command
unless arguments are passed to docker run, in this case those arguments are used instead.
used to set a permanent environment variable that can always be
accessed by the container, you may ask why is that even a thing since we can just
use "RUN export" and set our env vars, the problem with this approach is that the
env var will not be accessible by next instructions since this it will only be
available for the process which used it( {default-shell } export) and will not be
remembered by docker since it does only commit file system changes and not process
environment, thats where the ENV instruction becomes handy, since it makes dockerd
inject the environment variables every time a new container is started from the image.
the variable can also be used in the docker file itself.
looks for 'host-path' (can be files or dirs) in the build context (a path specified in
the docker build command) and copies them to the 'container-path', if the resource
specified in 'host-path' is not found in the the build context docker build will fail
this instruction does the same thing as COPY, except that it does have some extra features:
first: automated extraction of tar archives for example : ADD file.tar.gz ./ will
extract the file to './' in the container file system.
second: remote url fetching, which means 'src' can be a path to an online resource that will be stored in
the 'dest' which should be a path in your container file system.
however, using remote URLs and automatic extraction is discouraged for reproducibility and security reasons.
prefer using COPY unless you explicitly need these features.