Friday, 17 April 2020

All about Docker : Part 2

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