Introduction to the
Dockerfile
What is the Dockerfile?
Dockerfiles are
instructions. They contains all of the commands used to build an image.
- Docker images consist of read-only layers.
- Each represents a Dockerfile instruction.
- Layers are stacked.
- Each layer is a result of the changes from
the previous layer.
- Images are built using the docker image build
command.
Dockerfile Layers
Dockerfile:
FROM ubuntu:15.04
COPY . /app
RUN make /app
CMD python /app/app.py
- FROM creates a layer from the ubuntu:15.04
Docker image.
- COPY adds files from your Docker client’s
current directory.
- RUN builds your application with make.
- CMD specifies what command to run within the
container.
Best Practices
General guidelines:
- Keep containers as ephemeral as possible.
- Follow Principle 6 of the 12 Factor App.
- Avoid including unnecessary files.
- Use .dockerignore.
- Use multi-stage builds.
- Don’t install unnecessary packages.
- Decouple applications.
- Minimize the number of layers.
- Sort multi-line arguments.
- Leverage build cache.
Working with Instructions
FROM: Initializes a new
build stage and sets the Base Image
RUN: Will execute any
commands in a new layer
CMD: Provides a default
for an executing container. There can only be one CMD instruction in a
Dockerfile
LABEL: Adds metadata to an
image
EXPOSE: Informs Docker
that the container listens on the specified network ports at runtime
ENV: Sets the environment
variable <key> to the value <value>
ADD: Copies new files,
directories or remote file URLs from <src> and adds them to the
filesystem of the image at the path <dest>.
COPY: Copies new files or
directories from <src> and adds them to the filesystem of the container
at the path <dest>.
ENTRYPOINT: Allows for
configuring a container that will run as an executable
VOLUME: Creates a mount
point with the specified name and marks it as holding externally mounted
volumes from native host or other containers
USER: Sets the user name
(or UID) and optionally the user group (or GID) to use when running the image
and for any RUN, CMD, and ENTRYPOINT instructions that follow it in the
Dockerfile
WORKDIR: Sets the working
directory for any RUN, CMD, ENTRYPOINT, COPY, and ADD instructions that follow
it in the Dockerfile
ARG: Defines a variable
that users can pass at build-time to the builder with the docker build command,
using the --build-arg <varname>=<value> flag
ONBUILD: Adds a trigger
instruction to the image that will be executed at a later time, when the image
is used as the base for another build
HEALTHCHECK: Tells Docker
how to test a container to check that it is still working
SHELL: Allows the default
shell used for the shell form of commands to be overridden
To set up the environment:
sudo yum install git -y
mkdir docker_images
cd docker_images
mkdir corona-app
cd corona-app
git clone https://github.com/pkadre/content-corona-app.git src
Create the Dockerfile:
vi Dockerfile
Dockerfile contents:
# Create an image for the corona-app
FROM node
LABEL org.label-schema.version=v1.1
RUN mkdir -p /var/node
ADD src/ /var/node/
WORKDIR /var/node
RUN npm install
EXPOSE 3000
CMD ./bin/www
Build the corona-app
image:
docker image build -t pkadre/corona-app:v1 .
List the images:
docker image ls
Create the corona-app
container:
docker container run -d --name corona-app1 -p 8081:3000
pkadre/corona-app:v1
List all running
containers:
docker container ls
Environment Variables
To make new software
easier to run, you can use ENV to update the PATH environment variable for the
software that your container installs.
Setup your environment:
cd docker_images
mkdir env
cd env
Use the --env flag to pass
an environment variable when building an image:
--env [KEY]=[VALUE]
Use the ENV instruction in
the Dockerfile:
ENV [KEY]=[VALUE]
ENV [KEY] [VALUE]
Clone the corona-app:
git clone https://github.com/pkadre/content-corona-app.git src
Create the Dockerfile
vi Dockerfile
Dockerfile contents:
# Create an image for the corona-app
FROM node
LABEL org.label-schema.version=v1.1
ENV NODE_ENV="development"
ENV PORT 3000
RUN mkdir -p /var/node
ADD src/ /var/node/
WORKDIR /var/node
RUN npm install
EXPOSE $PORT
CMD ./bin/www
Create the corona-app
container:
docker image build -t pkadre/corona-app:v2 .
Inspect the container to
see the environment variables:
docker image inspect pkadre/corona-app:v2
Deploy the corona-dev
application:
docker container run -d --name corona-dev -p 8082:3001 --env PORT=3001
pkadre/corona-app:v2
Inspect the development
container to see the environment variables:
docker container inspect corona-dev
Deploy the corona-app to
production:
docker container run -d --name corona-app2 -p 8083:3001 --env PORT=3001
--env NODE_ENV=production pkadre/corona-app:v2
Inspect the production
container to see the environment variables:
docker container inspect corona-app2
Get the logs for
corona-app2:
docker container logs corona-app2
docker container run -d --name corona-prod -p 8084:3000 --env
NODE_ENV=production pkadre/corona-app:v2
Build Arguments
Use the --build-arg flag
when building an image:
--build-arg [NAME]=[VALUE]
Use the ARG instruction in
the Dockerfile:
ARG [NAME]=[DEFAULT_VALUE]
Navigate to the args
directory:
cd docker_images
mkdir args
cd args
Clone the corona-app:
git clone https://github.com/pkadre/content-corona-app.git src
Create the Dockerfile:
vi Dockerfile
Dockerfile:
# Create an image for the corona-app
FROM node
LABEL org.label-schema.version=v1.1
ARG SRC_DIR=/var/node
RUN mkdir -p $SRC_DIR
ADD src/ $SRC_DIR
WORKDIR $SRC_DIR
RUN npm install
EXPOSE 3000
CMD ./bin/www
Create the corona-app
container:
docker image build -t pkadre/corona-app:v3 --build-arg SRC_DIR=/var/code .
Inspect the image:
docker image inspect pkadre/corona-app:v3 | grep WorkingDir
Create the corona-app
container:
docker container run -d --name corona-app3 -p 8085:3000
pkadre/corona-app:v3
Verify that the container
is working by executing curl:
curl localhost:8085
Building Images
To build image:
docker image build -t <NAME>:<TAG> .
Useful flags:
- -f, --file string: This is the name of the
Dockerfile (Default is PATH/Dockerfile).
- --force-rm: Always remove intermediate
containers.
- --label list: Set metadata for an image.
- --rm: Remove intermediate containers after a
successful build (default is true).
- --ulimit ulimit: This sets ulimit options
(default is []).
cd docker_images/corona-app
cp Dockerfile Dockerfile.test
docker image build -t pkadre/corona-app:path-example1 -f Dockerfile.test .
docker image build -t pkadre/corona-app:path-example2 --label
com.pkadre.version=v1.8 -f Dockerfile.test .
Building image by piping
the Dockerfile through STDIN:
docker image build -t <NAME>:<TAG> -<<EOF
Build instructions
EOF
Example:
docker image build -t pkadre/nginx:stind --rm -<<EOF
FROM nginx:latest
VOLUME ["/usr/share/nginx/html/"]
EOF
Building an image using a
URL:
docker image build -t <NAME>:<TAG> <GIT_URL>#<REF>
docker image build -t <NAME>:<TAG>
<GIT_URL>#:<DIRECTORY>
docker image build -t <NAME>:<TAG>
<GIT_URL>#<REF>:<DIRECTORY>
Example:
docker image build -t pkadre/corona-app:github
https://github.com/pkadre/content-corona-app.git#remote-build
Building an image from a
zip file:
docker image build -t <NAME>:<TAG> - < <FILE>.tar.gz
Example:
cd docker_images
mkdir tar_image
cd tar_image
git clone https://github.com/pkadre/content-corona-app.git
cd content-corona-app
git checkout remote-build
tar -zcvf corona-app.tar.gz Dockerfile src
docker image build -t pkadre/corona-app:from-tar - < corona-app.tar.gz
Using Multi-Stage
Builds
- By default, the stages are not named
- Stages are numbered with integers
- Starting with 0 for the first FROM
instruction
- Name the stage by adding as to the FROM
instruction
- Reference the stage name in the COPY
instruction
Set up your environment:
cd docker_images
mkdir multi-stage-builds
cd multi-stage-builds
git clone https://github.com/pkadre/content-corona-app.git src
Create the Dockerfile:
vi Dockerfile
Dockerfile contents:
# Create an image for the corona-app using multi-stage build
FROM node AS build
RUN mkdir -p /var/node/
ADD src/ /var/node/
WORKDIR /var/node
RUN npm install
FROM node:alpine
ARG VERSION=V1.1
LABEL org.label-schema.version=$VERSION
ENV NODE_ENV="production"
COPY --from=build /var/node /var/node
WORKDIR /var/node
EXPOSE 3000
ENTRYPOINT ["./bin/www"]
Build the image:
docker image build -t pkadre/corona-app:multi-stage-build --rm --build-arg
VERSION=1.5 .
List images to see the
size difference:
docker image ls
Create the corona-app
container:
docker container run -d --name multi-stage-build -p 8087:3000
pkadre/corona-app:multi-stage-build
Tagging
Add a name and an optional
tag with -t or --tag, in the name:tag format:
docker image build -t <name>:<tag>
docker image build --tag <name>:<tag>
List your images:
docker image ls
Use our Git commit hash as
the image tag:
git log -1 --pretty=%H
Use the Docker tag to a
create a new tagged image:
docker tag <SOURCE_IMAGE><:TAG>
<TARGET_IMAGE>:<TAG>
Get the commit hash:
cd docker_images/corona-app/src
git log -1 --pretty=%H
cd ../
Build the image using the
Git hash as the tag:
docker image build -t pkadre/corona-app:<GIT_HASH> .
Tag the corona-app as the
latest using the image tagged with the commit hash:
docker image tag pkadre/corona-app:<GIT_HASH>
pkadre/corona-app:latest
Docker Events
Get real-time events from
the server:
docker system events
docker system events --since '<TIME_PERIOD>'
Start a new CentOS
container:
docker container run -itd --name docker_events centos /bin/bash
Listen for events:
docker system events
Generate Events:
docker container exec docker_events /bin/bash
docker container attach docker_events
docker container start docker_events
Filters Events:
docker system events --filter <FILTER_NAME>=<FILTER>
Filter for container
events:
docker system events --filter type=container --since '1h'
Generate an event:
docker container exec docker_events ls /
Filter for container
events:
docker system events --filter type=container --filter event=start --since
'1h'
List / on docker_events:
docker container exec docker_events ls /
Filter for attach events:
docker system events --filter type=container --filter event=attach
Connect to docker_events
using /bin/bash:
docker container exec -it docker_events /bin/bash
Attach to docker_events:
docker container attach docker_events
Connect to docker_events
using /bin/bash:
docker container exec -it docker_events /bin/bash
Attach to docker_events:
docker container attach docker_events
Use multiple filters:
docker system events --filter type=container --filter event=attach
--filter event=die --filter event=stop
Start docker_events:
docker container start docker_events
Attach to docker_events:
docker container attach docker_events
Documentation
https://docs.docker.com/engine/reference/commandline/events/
https://docs.docker.com/engine/api/v1.24/
Managing Stopped
Container
Remove one or more
containers:
docker container rm <NAME>
List the rm flags:
docker container rm -h
Start one or more stopped
containers:
docker container start <NAME>
Remove all stopped
containers:
docker container prune
List the IDs of all
containers:
docker container ls -a -q
List all stopped
containers:
docker container ls -a -f status=exited
List the IDs of stopped
containers:
docker container ls -a -q -f status=exited
Get a count of all stopped
containers:
docker container ls -a -q -f status=exited | wc -l
Get a listing of our
containers:
docker container ls -a -f status=exited | grep prometheus
Start Prometheus:
docker container start prometheus
Fin stopped corona-app
containers with grep:
docker container ls -a -f status=exited | grep corona-app
Remove stopped corona-app
containers:
docker container rm [CONTAINER_IDS]
Prune all stopped
containers:
docker container prune
No comments:
Post a Comment