- Introduction to Docker
Dockerfile
primer- Docker
compose
- Images
- Containers
- List the running containers
- List all the containers
- Create, Run and Stop containers
- See container Logs
- Container Port Mapping
- Data Persistence for Docker Containers
Table of contents generated with markdown-toc
Docker is a platform/ecosystem around creating and running containers. It's components include:
- Docker Client
- Docker Server/Daemon
- Docker Machine
- Docker Images
- Docker Container
- Docker Hub
- Docker Compose
Tool used to issue commands to the Docker Server/Daemon.
Tool responsible for creating images, running containers etc.
To be written..
Single file with all the dependencies and configuration to run a program.
In other words:
Docker image is a snapshot of a very specific file-system(FS) or directories along-with a startup command.
When a container is run, the kernel isolates a section of the hard-drive and places the image's File-system snapshot into that section and makes it available to the container which uses this image.
The kernel also allocates some portion of the CPU, memory and network to this container.
So, all the processes inside this container are namespaced to this very specific FS section on the hard-drive.
Note:
The resource namespacing concept is specific to the Linux Operating System only and does not apply to the MacOS and Windows OS. The docker version built for MacOS and Windows actually installs a Linux virtual machine on your system, that Linux VM then runs all the containers inside it.
To be written..
To be written..
Instance of a Docker image. Runs a program.
Container is a process of set of processes that has a grouping of resources assigned to it. Container has processes running in it, which make a system call to the OS kernel which then interacts with the underlying hardware(namespaced hardware i.e the calling process has been namespaced to a set of hardware resources; network, memory, CPU, hard disk) The kernel directs the system call to the appropriate hardware resources depending on the process which made the system call.
Steps
- Use a Base Image (with
FROM
) - Specify the working directory of the container (with
WORKDIR
) - Copy any files/directories(no remote files) from your
build context
to the container's file system (withCOPY
) - Copy any files/directories from
build context
and remote files to the container's file system (withADD
) - Run shell commands in container (with
RUN
) - Set container's startup command (with
CMD
) - Set environment variable (with
ENV
) - Expose a port of the container (with
EXPOSE
) - Specify an entrypoint (with
ENTRYPOINT
)
Its a separate CLI(other than Docker CLI) that gets installed with Docker. Used to start up multiple docker containers at the same time. Automates some of the long-winded arguments we pass to the docker run
.
Note:
The containers spawned usingDocker Compose
file are part of the same network and can communicate with each other freely without having the need of exposing ports to one another. They communicate with each other using their names. Names are assigned in the docker compose file.
Well, they can do so by using their service
name which is specified in the docker compose
file for that container.
Suppose we have 2 services/containers named node-app and postgres in a docker compose file. Then, the node-app container can communicate with the postgres container by just using its name postgres instead of its IP address in the network.
docker-compose.yml
version: '3'
services:
postgres:
image: postgres
node-app:
build: .
ports:
- "5000:8081"
Explanation:
The above docker-compose.yml file launces 2 containers; postgres and node-app.
postgres container uses an already built image and node-app builds from a given Dockerfile
in the build context
i.e the .
directory.
The host's port 5000 is mapped to the node-app container's 8081 port.
another example
version: '3'
services:
web:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
volumes:
- /app/node_modules #not mapped to any directory of host system
- .:/app #build_context . mapped to /app directory of the container
Run this docker compose file
docker compose up
Services are sort of docker containers. Services can take arguments, some of the arguments are:
- Image (existing image or build from
Dockerfile
) - Port mappings (between the host and the container, containers can communicate with each other without any port mapping; see the note above)
In a directory with a docker-compose.yml
file, run
sudo docker compose up
sudo docker compose up -d
In a directory with a docker-compose.yml
file, run
sudo docker compose up --build
sudo docker compose down
While in the directory having a Dockerfile, run
sudo docker build -t your-docker-id/repo:version build_context
where build_context
is the directory you want to use for the build.
and your-docker-id
is your docker ID.
The
version
is also calledtag
of the container.
usage example
sudo docker build -t my-image/my-project:second .
To run a file named Dockerfile.dev
sudo docker build -f filename_here build_context
i.e
sudo docker build -f Dockerfile.dev .
sudo docker images
sudo docker image rm image-name
Let's say you have a container 28006428a86d running, and you want to create a new image after you made changes in the container. Generating another image will allow you to preserve your changes.
sudo docker commit -p -a 'author name' -m 'message here' container-id-or-name name-of-new-image
-p
pauses the container while commit command is building the new image.-a
allows you to supply author information of the new image.-m
allows you to add a comment just as in the Git.
sudo docker commit -c "CMD ['startup-command-here']" container-id-or-name name-of-new-image
sudo docker commit -a 'author name' -m 'message here' container-id-or-name name-of-new-image
sudo docker ps
List the created, running, stopped and exited containers
sudo docker ps -a
Note:
Docker run command is an equivalent of two commands. Thedocker create
anddocker start
command.
Prepares the image's file-system snapshot to be used in the container
sudo docker create --name some-name image-name
The docker start
command starts the container in detached
(background) mode, while docker run
starts the container in attached
(foreground) mode.
Being attached
means that we're listening to the output of the container(i.e we're connecting to the STDOUT
of that container)
Executes the image's startup command, but does not show the container's output unless specified(can specify using logs
command and run
command displays logs by default).
sudo docker start container-name-or-id
Print the container's output to your terminal, with -a
flag
sudo docker start -a container-name-or-id
Waits 10 seconds for container to stop automatically, if it doesn't it gets killed with a fallback docker kill
command.
sudo docker stop container-name-or-id
Kills it immediatley
sudo docker kill container-name-or-id
sudo docker start container-name-or-id
It also deletes the container cache
sudo docker system prune
Creates a container from image and shows the output of the container on your terminal.
sudo docker run -it image-name bash
can give it a name, with --name
sudo docker run -it --name my-container image-name bash
Runs in background and can take commands from outside, with docker exec
sudo docker run -dit image-name bash
docker exec -it container_id_or_name echo "Hello from container!"
Example: You can use this to run rails console
on a container which is running and(maybe there's a server running on it)
Example of such a command
docker exec -it container_id_or_name rails console
sudo docker attach container-name-or-id
sudo docker run container-name-or-id command-goes-here
example
sudo docker run container-name-or-id echo Hello World
Note:
The command you're specifying here should be supported by the image dependencies/libs, otherwise it won't work.
It does not re-run the container
sudo docker logs container-name-or-id
- The Container must have exposed it's respective port(i.e in the Dockerfile)
Syntax
sudo docker container run --publish host-port:container-port image-id
Example
sudo docker container run --publish 80:3000 image-id
It direct the host's port# 80's traffic to the container's port# 3000.
This is a
runtime
action and cannot be specified inside a Dockerfile.
-
There are two multiple to use persistant data for a docker container. Two of them are;
- Bind Mounts
- Volumes
Volumes can be named
or anonymous
.
sudo docker volume create volume-name
sudo docker volume ls
sudo docker volume inspect volume-name
sudo docker volume rm volume-name
sudo docker run -d --name my-container -v directory-from-build_context:/directory-in-container image-name
This -v
or --volume
flag maps directory-from-build_context
to the directory-in-container
i.e any changes done to either are reflected in both the places(confirm this....).
- Skip the
directory-from-build_context
and just specify thedirectory-in-container
when giving the volume details i.e
sudo docker run -v /config/application.yml
This will prevent the /config/application.yml
directory in the container being mapped to any directory in the build_context
.
i.e the /config/application.yml
of the container remains unchanged, no matter what happens to it's build_context
directory counterpart.
Summary: Multiple docker images can be used as base images to build a new docker image.
Dockerfile
<!-- Phase 1: Builds a node app for production -->
FROM node:alpine as builder
WORKDIR '/app'
COPY package.json
RUN npm install
COPY . .
RUN npm run build
<!-- Phase 2: Run phase; use content from Phase 1 and do more stuff -->
FROM nginx
COPY --from=builder /app/build /usr/share/nginx/html