You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A sandboxed process on your machine that is isolated from all other processes on the host machine
is a runnable instance of an image. You can create, start, stop, move, or delete a container using the DockerAPI or CLI.
can be run on local machines, virtual machines or deployed to the cloud.
is portable (can be run on any OS)
Containers are isolated from each other and run their own software, binaries, and configurations.
How?
Leverages kernel namespaces and cgroups, features that have been in Linux for a long time
container IMAGE
When running a container, it uses an isolated filesystem. This custom filesystem is provided by a container image.
Since the image contains the container’s filesystem, it must contain everything needed to run an application - all dependencies, configuration, scripts, binaries, etc.
The image also contains other configuration for the container, such as environment variables, a default command to run, and other metadata.
Comparison to chroot
If you’re familiar with chroot, think of a container as an extended version of chroot.
The filesystem is simply coming from the image.
But, a container adds additional isolation not available when simply using chroot.
Dockerfile
Simply a text-based script of instructions that is used to create a container image. docker build -t IMAGE_TAG . docker run IMAGE_TAG
docker build [OPTIONS] CONTEXT
The docker build command builds an image from a Dockerfile and a context. context == directory or git repository url.
Place your Dockerfile into the CONTEXT.
Layers
https://docs.docker.com/storage/storagedriver/
There is a common technique to delete files within the same RUN command that they were created in.
This is because once a layer is created, a file cannot be deleted from it.
Thus, best practise is to use multi-stage builds if you worry about this problem and are generating a lot of intermediaty files.
Thin top Writable layer
When you run a container Image, any writes that the running container performs are stored in the top most layer. When the container is deleted, so is this layer. Thus running an image creates a clean slate.
This top layer can also be stored/commited to an imageFile if you so desire.
Both ARG and ENV are not expanded in ENTRYPOINT or CMD
But ENV is passed to the shell.
Supplied at build-time to docker build with --build-arg <varname>=<value>
The Dockerfile defines the ARG's existence with ARG varname=default.
The arg variable only exists after it has been declared in a line on the Dockerfile. Only lines after that will have a value for the arg.
They also come out of scope at the end of each build stage / (before next FROM instruction). But you can bring them back into scope by repeating the declaration, ARG varname=default or ARG varname (no defaults).
FROM
repositoryName/imageName:tagVersion
eg. FROM i386/ubuntu:bionic AS builder
The tag or digest values are optional. If you omit either of them, the builder assumes a latest tag by default. The builder returns an error if it cannot find the tag value.
The optional --platform flag can be used to specify the platform of the image in case FROM references a multi-platform image. For example, linux/amd64, linux/arm64, or windows/amd64. By default, the target platform of the build request is used
SHELL COMMAND
This command sets the shell for the STRING/SHELL forms of : RUN, CMD and ENTRYPOINT. SHELL ["executable", "parameters"]
By default it is /bin/sh -c.
CMD and ENTRYPOINT
There are 2 forms, JSON_FORM/EXEC_FORM and STRING_FORM/SHELL_FORM.
STRING_FORM wraps the command and its arguments in a SHELL (default=/bin/sh -c).
The JSON_FORM of ENTRYPOINT means your process is PID=1, String form NOT.
Shell/String Form
This is space separated like: CMD bash myfile.sh > /dev/zero
It is nicknamed Shell form because its essentially wrapping the arguments with bash -c ${YOUR_STRING}
DIRECT/JSON_OBJECT Form
This is in a json-array like syntax. CMD ["bash", "myfile.sh", ">" ,"/dev/zero"]
The command becomes the process Parent. It is forked.
When to use ENTRYPOINT?
ENTRYPOINT can be extended by the command-line ( in DIRECT/JSON_OBJECT form )
ENTRYPOINT should be defined when using the container as an executable. Because it supports argument extension.
HOWEVER you can enforce the runtime by using Shell/String form. It disables both CMD and runtime args. Only disadvantage is that you are not PID 1, bash is.
When to use CMD?
CMD are temporary because can be overriden by user.
When you specify CMD in Dockerfile you are really specifying a default, as they will be overridden by any run-time arguments.
CMD should be used as a way of defining default arguments for an ENTRYPOINT command
Shell/String ENTRYPOINT disables CMD.
If ENTRYPOINT im a string => /bin/sh -c im a string.
DIRECT/JSON_OBJECTENTRYPOINTwithDIRECT/JSON_OBJECTCMD == prog1 arg1 prog2 arg2 - as you can see the CMD prog2/arg2 are used as parameters to prog1 - Summary = Concatenation = Double Direct.
DIRECT/JSON_OBJECTENTRYPOINTwithShell/StringCMD == prog1 arg1 /bin/sh -c prog2 arg2 - Summary - /bin/sh is passed to the ENTRYPOINT, so this one is quite odd.
If wrapped in /bin/sh -c, signals are not passed, can be fixed with ENTRYPOINT exec YOURCMD ARG1.
simplified TLDR:
** THERE ARE ONLY 2 CASES TO REMEMBER, THE OTHER IS WEIRD **
Use Only DIRECT/JSON_OBJECT of ENTRYPOINT.
UseCase = No Shell Syntax, PID1, CommandLine appended.
Use Only Shell/String of CMD.
UseCase = Access To Shell Syntax, Fully Overidable by commandLine.
Together
Use DIRECT/JSON_OBJECT of ENTRYPOINT plus Exec form CMD for using CMD as "arguments" to ENTRYPOINT, where these arguments can be overriden by docker run <arguments>.
UseCase = No Shell Syntax, PID1, Default Arguments overidable by CommandLine.
Use DIRECT/JSON_OBJECT form of ENTRYPOINT plus String form CMD which appends bin/sh -c prog2 arg2, making the arguments seem a bit weird, not sure what this is use case is!
UseCase = Unsure
docker run command line overriding ENTRYPOINT and CMD
arguments passed to docker run images ... :
ignored if ENTRYPOINT is Shell/String
will OVERRIDE all forms of CMD
will be APPENDED to ENTRYPOINT if DIRECT/JSON_OBJECT_FORM
RUN
has lower case Shell/String like CMD and ENTRYPOINT
and json [] exec form.
By default it is /bin/sh -c
The RUN instruction will execute any commands in a new layer on top of the current image and commit the results. The resulting committed image will be used for the next step in the Dockerfile
The cache for RUN instructions isn’t invalidated automatically during the next build.
The cache for RUN instructions can be invalidated by using the --no-cache flag. docker build --no-cache
COPY
This is used to send files/folders INTO the built image.
ADD
This is like COPY but also can automatically unpack/unzip files.
When a directory on the host is mounted to a directory in the container using the -v option, the default behavior is to use the files and directories in the host directory and hide the contents of the container directory.
If the target directory in the container is not empty and the source directory on the host is empty, then the container directory contents will be visible in the mounted directory within the container.
However, if the source directory on the host is not empty and the target directory in the container is not empty, the behavior will depend on whether the -v option was used with the :ro (read-only) or :rw (read-write) option.
If the -v option was used with the :ro option, then the host directory contents will be visible in the mounted directory within the container, but any attempts to write to the mounted directory within the container will fail.
If the -v option was used with the :rw option, then the host directory contents will be visible in the mounted directory within the container, and any changes made to the mounted directory within the container will be reflected in the host directory.
When you use the VOLUME instruction in a Dockerfile, you are essentially creating a mount point for a volume in the container. This allows you to specify a directory that will be used as a data volume, which can be mounted from the host or from another container at runtime.
By copying files into the volume directory during the build process, you are essentially providing default contents for the volume. These contents will be visible in the volume when it is mounted in a container, unless the contents of the mount source (e.g., the host directory) take precedence because they are not empty.
Want empty directory?
Use volume?
Want to use a specific directory that has contents already?
Advantages similar to running in a Virtual Machine
Removes inconsistencies
Sandboxes projects
It just works, less hassle/time/effort run someone else work.
Comparing Docker Container to a non-docker Virtual Machine
VirtualMachine Example
Server
HostOS
Hypervisor
Kernel <-VirtualMachine
bins/libs <-VirtualMachine
apps <-VirtualMachine
Container Example
Server
HostOS
bins/libs <-CONTAINER
apps <-CONTAINER
Key Points
A Container is a running instance of an Image.
Containers will stop by themselves when the main procses exits.
1 Process per Container is recommended.
Image
An Image is a template for creating the environment you want it to snapshot of the system at a particualr time.
OS
Software
Application Code
All bundled up in a file.
You RUN images. Then they spawn containers.
Images are defined using a dockerfile.
Steps/recipe to create that image.
Image Name
The format for an image name is [registry:port]/repository/name:tag.
The [registry:port] is optional and defaults to registry-1.docker.io.
So usually its just : repositoryName/imageName:tagVersion
Tags
Tag is used to refer to a specific version/instance of a project/image
Whenever an image is tagged without an explicit tag, it’s given the latest tag by default
The Dockerfile
Create a Dockerfile
Build it to create an image
Run the image to spawn container
Example Dockerfile Loading another Dockerfile image prebuilt from hub.docker.com
FROM php:7.0-apache
COPY src/ /var/www/html
EXPOSE 80
Can mount files that change, option to share with the host.
-v /absolutePath/toHost:/absolutepath/tomounTo/
Its possible to make files permanent to an image, by comitting a container to an image,after its ran.
Running an Image /w Docker Run
docker run [OPTIONS] imgrepo/imgname[:TAG|@DIGEST] [COMMAND] [ARG...]
eg.
docker run -p 80:80 hello-world
some options
--rm Automatically remove the container when it exits
-i Interactive, keep STDIN open even if not attached
-t Allocate a pseudo-TTY
Pseudo TTy
xterm -> ptmx (pty master) -> pts (pty slave) -> bash
user sends command to bash.
'tty' command, shows pseudo-terminal
bash's natural TTY slave
If the program that you are launching supports connecting to a pesudo terminal like a 'shell' eg. like bash, sh, dash. Then you supply -t
So, with that as background
run a container with no options and by default you have a stdout stream (so docker run | works);
run with -i, and you get stdin stream added (so | docker run -i works);
use -t, usually in the combination -it and you have a terminal driver added, which if you are interacting with the process is likely what you want.
It basically makes the container start look like a terminal connection session.
docker run/exec -i will connect the STDIN of the command inside the container to the STDIN of the docker run/exec itself.
-w workdir inside the directory
The default working directory for running binaries within a container is the root directory (/). It is possible to set a different working directory with the Dockerfile WORKDIR command
Any RUN, CMD, ADD, COPY, or ENTRYPOINT command will be executed in the specified working directory.
Removing A Container
docker ps
docker stop <containerId>
docker rm <containerId>
Execing into A container / Shell Access
docker exec <container-id> ls -la
Docker logfiles for container
docker logs "containerName/Id"
Alpine images are TINY in comparison to debian
Docker Volumes
You can manage volumes using Docker CLI commands or the Docker API.
Volumes work on both Linux and Windows containers.
Volumes can be more safely shared among multiple containers.
Volume drivers allow you to store volumes on remote hosts or cloud providers, to encrypt the contents of volumes, or to add other functionality.
A new volume’s contents can be pre-populated by a container.
Docker will manage them for us and they can not be accessed outside of Docker.
If the target directory has data, then they are copied into the newly auto-created volume.
Tmpfs mounts
Memory only
Bind Mounts
-v <host_abs_path>:<abs_path_mount_point> = bind mount volume
filesystem of host
Bind mounts exist on the host file system and being managed by the host maintainer.
Applications / processes outside of Docker can also modify it.
TLDR Volumes are a much wider solution
Removing volume
docker volume rm nginx-vol
More Volume Details
-v or --volume: Consists of three fields, separated by colon characters (:). The fields must be in the correct order, and the meaning of each field is not immediately obvious.
In the case of bind mounts, the first field is the path to the file or directory on the host machine.
The second field is the path where the file or directory is mounted in the container.
The third field is optional, and is a comma-separated list of options, such as ro, z, and Z. These options are discussed below.
Listing volumes and other meta-details
docker inspect <ContainerName>
Declaring the volume in the Dockerfile insures that the data will persist and will be available to the host
Docker Services
The docker run command creates and starts a container on the local docker host.
A docker "service" is one or more containers with the same configuration running under docker's swarm mode. It's similar to docker run in that you spin up a container. The difference is that you now have orchestration. That orchestration restarts your container if it stops, finds the appropriate node to run the container on based on your constraints, scale your service up or down, allows you to use the mesh networking and a VIP to discover your service, and perform rolling updates to minimize the risk of an outage during a change to your running application.
Dockerfiles
Commenting Lines
use the # , but must be at start of line. (except whitespace)
As such, a valid Dockerfile must start with a FROM instruction
ARG is the only instruction that may come before FROM in the Dockerfile
Multi-stage Builds
WithoutStageName
Simply make a note of the last image ID output by the commit before each new FROM instruction
FROM can appear multiple times within a single Dockerfile to create multiple images or use one build stage as a dependency for another.
Each FROM instruction clears any state created by previous instructions.
FROM image AS nameOfStage
Selectively building only one part of the dockerfile
docker build --target nameOfStage
Taking file from other image or previous stage
COPY --from nameOfStage
COPY --from nginx:latest
Use a previous stage as a new stage
FROM nameOfStage AS newStageName
Docker daemon interaction
List Built Images
docker images
-a ALL
-q ShortVersion
List Containers Running
docker ps
-a ALL
-q ShortVersion
Detaching from a container
Press Ctrl-P, followed by Ctrl-Q, to detach from your connection
Multiple Programs Problem
There can be only one ENTRYPOINT, but that target is usually a script that launches as many programs that are needed.
Say, You have one database that is used by a single web application. Then it is probably easier to run both in a single container.
If You have a shared database that is used by more than one application, then it would be better to run the database in its own container and the applications each in their own containers.
There are at least two possibilities how the applications can communicate with each other when they are running in different containers:
Use exposed IP ports and connect via them.
Recent docker versions support linking.
http://docs.docker.com/userguide/dockerlinks/#container-linking
Or Docker Networks
docker network create myNetwork
docker network connect myNetwork web1
docker network connect myNetwork web2
Now you connect from web1 to web2 container or the other way round.
Use the internal network IP addresses which you can find by running:
docker network inspect myNetwork
docker stop vs docker rm
docker stop
preserves the container in the docker ps -a list
which gives the opportunity to commit it if you want to save its state in a new image
sends SIGTERM first, then, after a grace period, SIGKILL.
docker rm
removes the container from docker ps -a list
losing its "state" - the layered filesystems written on top of the image filesystem.
It cannot remove a running container (unless called with -f, in which case it sends SIGKILL directly).
In term of lifecycle, you are supposed to stop the container first, then remove it. It gives a chance to the container PID 1 to collect zombie processes.
Reclaimin Space
From Containers
The docker container prune command removes all stopped Docker containers from your system. docker container prune docker ps -a