An overview of docker and its functionalities.
A cheat sheet of its common used commands
A yet minimal, simple to be complex guide on docker.
Based on The Docker Handbook but not only.
Click to expand
-
- Basic manipulations
- Publish a port
- Running a container in the background
- Listing Containers
- Naming & Renaming Container
- Stopping and killing a container
- Start and Restarting a Container
- Creating a container w/o running
- Removing Dangling Container
- Running a container in a interactive mode
- Executing command inside a container
- Working with executable images
According to IBM
Containuerization involves encapsulating or packaging software code and all its dependacies so that it can run uniformely and consistenly on any infrastructure
In a simple way, its lets you bundle up your software code along with all its depndacies in a self-contained package so that it can be run without going through a troublesome of setup process.
The key ideas are:
- Develop and run the app inside an isolated environment (container) that matches your final deployement environment
- Put the application in a single file (image) along with all its dependancies and necessary deployement configurations
- Share that image through a central server (registry) that is accessible by anyone with proper authorization.
Docker is just an implementation like others (Podman by RedHat, Kaniko by Google, rkt by CoreOS) of the concept of containeurisation. In short docker allows you to containerize your applications, share them using public or private registries, and also to or orchestrate them.
$ docker run hello-world
+ run the hello-world image
$ docker ps -a
+ list all past and current running containers
The offical Docker resources state:
A container is an abstraction at the application layer that packages code and dependencies together.
Instead of virtualizing the entire physical machine, containers virtualize the host operating system only.
Containers are completely isolated environments from the host system as well as from each other.
They're a lot lighter than the traditional VM and a large number of containers can be run simultaneously without affecting the performance of the host system. Containers are considered to be the next generation of virtual machines.*
The main difference is the method of virtualization.
Traditional VM | Containers |
---|---|
Created, managed by a hypervisor (OracleVM, VirtualBox,..) | Utilize the host OS via the container runtime while maintaining isolation |
The hypervisor sits between the host OS and the VM to act as a medium communication | The container runtime (Docker) sits between the container and the host OS |
Comes with its own guest OS which is heavy as the host OS | Doesn't need its own OS as it follows the idea behind containeurization |
The app inside the VM communicates with the guest OS which talks with the hypervisor which talks to the host OS ...(long chain of communication) | The container communicate with the container runtime which communicates with the host OS to get necessary resources. |
With it own OS, VM are heavier and more resources consuming | By eliminating the entire host OS, containers are much lighter and less ressource-hogging |
Traditional VM | Containers |
---|---|
These commands shows that docker uses the kernel of the host OS
$ uname -a
$ docker run alpine uname -a
Images are multi-layered self-contained files that act as the template for creating containers.They are like a frozen, read-only copy of a container and can be exchanged through registries.
The OCI (Open Container Initiative) defined a standard specification for images which is complied by the major containerization engines out there. a docker image can be used with another runtime like Podman without any additional hassle.
Containers are just image in running states.
A centralized place where you can upload your images and can also download images created by others. Docker Hub is the default public registry for Docker and Quay is another popular registry by Red Hat.
Docker as a software was designing in consist of three major components:
- Docker Daemon : The daemon( dockerd is a process running in the background and awaits for commands from the client.
- Docker Client : The client (docker) is a CLI program mostly responsible for transporting commands isued by users
- REST API : The rest API acts as a bridge between the daemon and the client. Any commands issued using the client passes through the API to finally reach the daemon.
Docker officials state:
"Docker uses a client-server architecture. The Docker client communicates with the the Docker daemon which does heavy lifting of building, running, and distributing your Docker containers."
Note : if the the image is not found in the local repository Unable to find image 'image-name'
will be printed on the terminal.
The Daemon will reach out to default public registry (Docker Hub) and pulls in the last copy of the image if found.
A new container will then be created from the freshly pulled image.
By default, Docker Daemon look for images in the hub that are not present locally and once an image has been fetched, it will stay in the local cache.
In case of newer images, the Daemon will fetch them automatically.
docker <object> <command> <options>
command syntax
-<object>
: type of docker object to be manipulated
-<command>
task to be carried by the Daemon
-<options>
: any valid parameter that can override the default behaviour of the command.docker run <image name>
ordocker container run <image name>
: run a container\- the
<option>
--publish or -p
is for port mapping\ Ctrl +C
: stop the container
As isolated environments as containers, the OS doesn't know nothing about what's going on inside them.
Hence applications running inside them reamin inaccessible from the outside.
To allow access from the outside, We must publish the appropriate port inside the container to a port on your local network.
The common sysntax is --publish or -p
--publish <host port> <container port>
docker run container --publish 8080:80 /repo/docker-image
: publish the image /repo/docker-image to the port 8080 locally.
Known as the detach mode, this mode keeps running the container int he background.
The option to be used is --detach or -d
Note that this command output the full CONTAINER ID of the newely created container on the terminal
docker run container --detach --publish 808:80 /repo/docker-image
output:
9e634a231ea4e37f94ef747a8ca6bd2bc25c473699afc783d5dce836bc341090
Note : The order of options doesn't really matter but anything that is been put after the image name will be passed as an argument to the container entry-point.
docker container ls
is the command to be used to list running containers.
the last column
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e634a231ea4 fhsinchy/hello-dock docker-entrypoint.…" 3 hours ago 3 hours ago 0.0.0.0:8080->80/tcp, :::8080->80/tcp optimistic_tereshkov
The CONTAINER ID is the first 12 characters of the full container ID printed out after running docke container run
The NAME is generated by docker
docker container ls -all | -a
will list all container that has ever run with the session in the OS.
The option --name
can be used to achieve the naming of a container and the option --rename
can be used to rename an existing container.
docker container run --detach --publish 8888:80 --name hello-dock-container fhsincy/hello-dock
The above code will create a new container with a user defined name 'hello-dock-container' and not a docker generated name.
docker container rename <container identifer> <new name>
will rename the name attached to container identifier(Id or name) to new name.
docker container rename optimistic_tereshkova new-nice-name
docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9e634a231ea4 fhsinchy/hello-dock "/docker-entrypoint.…" 4 hours ago Up 4 hours 0.0.0.0:8080->80/tcp, :::8080->80/tcp new-nice-name
While container running on foreground can be stopped by closing the terminal or combining Ctrl+C
, container running in the background need another docker command.
docker container stop <container ID or name>
Note : The above command will shut down a container gracefully by sending a SIGTERM
signal. we may use the below command to send a SIGKILL
signal.
docker container kill <container ID or name>
PS: Stopped container remain in the system and can restarted.
Two scenarios to be noticed here:
- Restarting a container that has been previously stopped or killed
- Rebooting a running container
The command below will start any stopped or killed container
docker container start <container ID or name>
Stopped or killed container can be viewed with an EXIT
status in the output of docker contaienr ls --all
docker container start hello-dock-container
Note that the container start will start a container in detached mode and will retain any port configuration made previously.
Rebooting a running container can be done with:
docker container restart <container ID or name>
The main difference between starting and restarting a container is that the container restart
command attemps to stop the target container and start it back while the start
command aims to start an already stopped command.
In case of a stopped container, both commands are exactly the same. But in case of a running container, you must use the container restart command.
docker container run <container-image>
The command above used two differents commands which are:
docker container create
creates a container from a given name
docker container start
starts an already created container
docker container create --publish 8080:80 fhsinchy/hello-dock
docker container start fhsinchy/hello-dock
The command above will create the hello-dock container.
Containers that have been stopped or or killed remain in the system. These dangling containers can take up spaces or create conflict with newer containers.
The command container rm <container ID or name>
can be used in order to remove a stopped container.
docker container rm busy_mashivara
Note that multiple containers can be removed by passing their ID one after another separated by space.
To remove all dangling container, we can use the command below:
docker container prune
The option --rm
for the docker container run
allows to indicated that our container should be removed once stopped or killed.
docker container run --rm --detach --publish 8383:80 --name hello-volatile fhsinchy/hello-dock
Images can hold or can carry on programs that are interactive with the user running them, all images are not so simple as what've been seen previously.
Popular distribution such as Fedora, Ubuntu, Debian, ... have docker image in the hub\ Programming language such as python, php, java, javascript, ... etc do also have their official image in the hub.
Such images are configured to run a shell by command, in case of the OS it can be something like bash
or sh
and programming languages usually use their default shell.
The option -it (or --interactive --tty)
for container run
command will run an image in interactive mode as :
docker container run --rm -it ubuntu
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
345e3491a907: Pull complete
57671312ef6f: Pull complete
5e9250ddb7d0: Pull complete
Digest: sha256:cf31af331f38d1d7158470e095b132acd126a7180a54f263d386da88eb681d93
Status: Downloaded newer image for ubuntu:latest
root@20fc27827b42:/ # uname -a
Linux 20fc27827b42 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 x86_64 x86_64 GNU/Linux
root@20fc27827b42:/ # ls
bin dev home lib32 libx32 mnt proc run srv tmp var
boot etc lib lib64 media opt root sbin sys usr
root@20fc27827b42:
Image can also be configured to receive arguments and perform a certain task.
Docker is set to treat every string and/or numeric that comes after the image name to be treated as an argument.
docker run --rm alpine uname -a
Linux 68bc1f23d028 4.19.0-16-amd64 #1 SMP Debian 4.19.181-1 (2021-03-19) x86_64 Linux
In the command above the uname -a is passed through the alpine image and get executed.
Executable images are meant to behave as executable programs.
Some of these images are designed to perform task with local OS files, it could be deleting corrupted files, creating or installing programs, ... etc.
Using bind mounts helps granting a container direct access to our local files system.
A bind mount lets us perform a two way data binding between the container of a local file system directory (source) and another directory inside a container (destination).
This way any changes made in the destination directory will take effect on the source directory and vise versa.
touch hvt.pdf
fabric@km:~$ touch a.pdf c.pdf e.pdf off.pdf
fabric@km:~$ docker container run --rm -v $(pwd):/zone fhsinchy/rmbyext pdf
Unable to find image 'fhsinchy/rmbyext:latest' locally
latest: Pulling from fhsinchy/rmbyext
801bfaa63ef2: Already exists
8723b2b92bec: Pull complete
4e07029ccd64: Pull complete
594990504179: Pull complete
140d7fec7322: Pull complete
23038161e8da: Pull complete
0b40a42464a5: Pull complete
Digest: sha256:58969069a70a7f9b29be83abd1465cf10c568049c9d183e9d7a7d8726d074048
Status: Downloaded newer image for fhsinchy/rmbyext:latest
Removing: PDF
c.pdf
hvt.pdf
e.pdf
a.pdf
off.pdf
The image fhsinchy/rmbyext
is an executable one that delete file by extensions. We used bind mount to bind the zone/
directory in the contianer to our local filesystems. We created some .pdf files and deleted them with the executable container.
The option -v (or --volume) $(pwd):zone/
a seen is used for creating a bind mount for a container, it can take three fields separated by (:
). The generic systax is as follow :
--volume <local file system directory absolute path>:<container file system directory absolute path>:<read write access>
The third field is optional but you must pass the absolute path of your local directory and the absolute path of the directory inside the container.
The difference between a regular image and an executable one is that the entry-point for an executable image is set to a custom program instead of sh, in this case the rmbyext program.
And as you've learned in the previous sub-section, anything you write after the image name in a container run command gets passed to the entry-point of the image.
So in the end the docker container run --rm -v $(pwd):/zone fhsinchy/rmbyext pdf
command translates to rmbyext pdf
inside the container. Executable images are not that common in the wild but can be very useful in certain cases.
Creating, running, and sharing images online.
Images are multi-layered self-contained files that act as the template for creating docker contaienrs; kind of like a frozen, read-only type of container.
To create one, we must have a clear vision of what we want from the image. Ex: the image should run apache server, nginx, ... etc
Let's create our own custom nginx docker image that behaves like the official one which aims to run nginx on localhost once started.
Our vision of the image could be like:
- The image should have NGINX pre-installed which can be done using a package manager or can be built from source
- Upon running, the image should start NGINX
To achieve that, we create a Dockerfile with 'Dockerfile'.
A dockerfile is a set of instructions once executed by the daemon result in an image. It content could look like:
FROM ubuntu:latest # every valid dockerfile start with FROM
# setting the base image for the resultant image
EXPOSE 80 # indicate the port that needs to be published
# RUN execute a command inside the container shell
RUN apt-get update && \
apt-get install nginx -y && \
apt-get clean && rm -rf /var/lib/apt/lists/* # used for clearing package cache so unecessary baggage
# set the default command for the image
# written in exec mode but can also be written in shell mode
# nginx refers to the exec of nginx and -g daemon off are option for the command nginx
CMD ["nginx", "-g", "daemon off;"]
To build the image we use the command
docker image <command> <options>
We might use docker image build .
to build the image from the dockerfile we just wrote in the current folder we're in.
The daemon find any file named Dockerfile in the specified director and build the image based to it.
Setting up nginx (1.18.0-0ubuntu1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.2) ...
Removing intermediate container ae4a677d9589
---> a1dd5cb62e66
Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
---> Running in ff731d5048b6
Removing intermediate container ff731d5048b6
---> 271ff7c9945f
Successfully built 271ff7c9945f
Notice that the build will always output the ID of the image if everything went perfect. Let's run the container of the image we just built.
$ docker container run --rm --detach --name custom-nginx-packaged --publish 8080:80 271ff7c9945f
2f23d718e9f6f389aaef13cb5f4e6afc033c38025ccf47e3e432fe6f1b5e70f5
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2f23d718e9f6 271ff7c9945f "nginx -g 'daemon of…" 38 seconds ago Up 35 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp custom-nginx-packaged
Instead of relying on the randomly generated ID of the image, we can assign a custom identifier to our images by using the -tag or -t
option to the docker image
with this generic syntax:
--tag <image repository>:<image tag>
The repository is usually the image name and the tag indicates a certain build or version. Ex: docker container run mysql:5.7
docker image build --tag custom-nginx:packaged .
Sending build context to Docker daemon 2.048kB
Step 1/4 : FROM ubuntu:latest
---> 7e0aa2d69a15
Step 2/4 : EXPOSE 80
---> Using cache
---> a4642d990b1e
Step 3/4 : RUN apt-get update && apt-get install nginx -y && apt-get clean && rm -rf /var/lib/apt/lists/*
---> Using cache
---> a1dd5cb62e66
Step 4/4 : CMD ["nginx", "-g", "daemon off;"]
---> Using cache
---> 271ff7c9945f
Successfully built 271ff7c9945f
Successfully tagged custom-nginx:packaged
To change the tag of an existing or an already built image we use:
docker image tag <image id> <image repository>:<image tag>
## or ##
docker image tag <image repository>:<image tag> <new image repository>:<new image tag>
docker image ls // list all images avalaibale
REPOSITORY TAG IMAGE ID CREATED SIZE
custom-nginx packaged 271ff7c9945f 8 hours ago 132MB
ubuntu latest 7e0aa2d69a15 4 weeks ago 72.7MB
Listed images can be removed by:
docker image rm <image identifier>
The identifier can be the image ID or the image repository. We must use the tag when we use the repository instead of the random ID
docker image rm custom-nginx:packaged
Untagged: custom-nginx:packaged
Deleted: sha256:271ff7c9945fd76d5347255c20bb6d7f13c326799aef339c09cc9c2d4435c42f
Deleted: sha256:a1dd5cb62e666951c0b0a8b6e8ca54fe42bfc36185432131782cd7a18d878627
Deleted: sha256:4621725ccf5e5422e936c19f5dfedbf9cc0297257ba88ed523950e05f610cd30
Deleted: sha256:a4642d990b1e2232265f10bdc6243cdb50e5fb0169035215fe4817e5e3517b08
To cleanup all un-tagged dangling image, we may use :
docker image prune --force (-f) # remove untagged dangling image without confirmation
## or ##
docker image prune | --force | --all (-a) ## remove all cached image with or without (--force) confirmation
image history
command is used to vizualise the many layers of an image.
docker image history custom-ngix:packaged
IMAGE CREATED CREATED BY SIZE COMMENT
fafb482a6d08 12 seconds ago /bin/sh -c #(nop) CMD ["nginx" "-g" "daemon… 0B
839d55a75553 16 seconds ago /bin/sh -c apt-get update && apt-get ins… 59.2MB
9653184ba483 About a minute ago /bin/sh -c #(nop) EXPOSE 80 0B
7e0aa2d69a15 4 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B
<missing> 4 weeks ago /bin/sh -c mkdir -p /run/systemd && echo 'do… 7B
<missing> 4 weeks ago /bin/sh -c [ -z "$(apt-get indextargets)" ] 0B
<missing> 4 weeks ago /bin/sh -c set -xe && echo '#!/bin/sh' > /… 811B
<missing> 4 weeks ago /bin/sh -c #(nop) ADD file:5c44a80f547b7d68b… 72.7MB
This image has 8 layers, the last one is the most recent. Let's dig deeper into these layers by ignoring the last 4.
-
7e0aa2d69a15
was created by/bin/sh -c #(nop) CMD
/bin/sh -c #(nop) CMD ["/bin/bash"]
which indicates that the default shell inside Ubuntu has been loaded successfully. -
9653184ba483
was created by/bin/sh -c #(nop) EXPOSE 80
which was the second instruction in your code. -
839d55a75553
was created by/bin/sh -c apt-get update && apt-get install nginx -y && apt-get clean && rm -rf /var/lib/apt/lists/*
which was the third instruction in your code. You can also see that this image has a size of 60MB given all necessary packages were installed during the execution of this instruction. -
Finally the upper most layer
fafb482a6d08
was created by/bin/sh -c #(nop) CMD ["nginx", "-g", "daemon off;"]
which sets the default command for this image.
Many read-only layers, each recording a new set of changes to the state triggered by certain istruction make the final image. Once we start a contianer we get a new writable layer on top of other layers.
A technical concept called a union file system is what have made the layering phenomenon that happens everytime we work with docker possible. As Wikipedia state :
It allows files and directories of separate file systems, known as branches, to be transparently overlaid, forming a single coherent file system.By utilizing this concept, Docker can avoid data duplication and can use previously created layers as a cache for later builds.
Contents of directories which have the same path within the merged branches will be seen together in a single merged directory, within the new, virtual filesystem.
This results in compact, efficient images that can be used everywhere.
The goal of this subsection is to learn and get familiar with more instructions.
In order to build NGNIX from source we need the source of ngnix.
We'll be following seven steps to get our final image:
- Getting a good base image for building applications such as ubuntu
- Install necessary build dependancies on the base image.
- Copy the
nginx-X.XX.X.tar.gz
file inside the image. - Extract the contents of the archive and get rid of it.
- Configure the build, compile and installthe program using the
make
tool. - Get rid of the extracted source code
- Run
nginx
executable. Let's create theDockerfile
as :
FROM ubuntu:latest
# install the standard packages that are necessary for building nginx
RUN apt-get update && \
apt-get install build-essential\
libpcre3 \
libpcre3-dev \
zlib1g \
zlib1g-dev \
libssl1.1 \
libssl-dev \
-y && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# copying the nginx file to the image
COPY nginx-1.19.2.tar.gz .
# extract contents using tar command
RUN tar -xvf nginx-1.19.2.tar.gz && rm nginx-1.19.2.tar.gz
# installing nginx inside the extracted folder using make
RUN cd nginx-1.19.2 && \
./configure \
--sbin-path=/usr/bin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-pcre \
--pid-path=/var/run/nginx.pid \
--with-http_ssl_module && \
make && make install
# removing the directory once the build & installation complete
RUN rm -rf /nginx-1.19.2
CMD ["nginx", "-g", "daemon off;"]
We build the image using :
docker image build --tag custom-nginx:built .
- Instead of hard coding the filename like
nginx.X.XX.X.tar.gz
we can create an argument usingARG
instruction, so we can easily change the version of the filename through the argument - We can let the daemon download the archive manually during the process using the
ADD
which is capable of adding files from the internet.
FROM ubuntu:latest
RUN apt-get update && \
apt-get install build-essential\
libpcre3 \
libpcre3-dev \
zlib1g \
zlib1g-dev \
libssl1.1 \
libssl-dev \
-y && \
apt-get clean && rm -rf /var/lib/apt/lists/*
# declare var and can be accessed using {ARGNAME}
ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"
# dowload the archive from the internet.
ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}
RUN cd ${FILENAME} && \
./configure \
--sbin-path=/usr/bin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-pcre \
--pid-path=/var/run/nginx.pid \
--with-http_ssl_module && \
make && make install
RUN rm -rf /${FILENAME}}
CMD ["nginx", "-g", "daemon off;"]
Running the container on port 80 :
docker container run --rm --detach --name custom-nginx-built --publish 8080:80 custom-nginx:built
c0d3377bf53d748bb3b498f65ab18240342a376d1ff21c4027a1860910d1a737
images should be lightweight and hold only what is necessary for them to be run.
In the previous image we built, there is a lot of dependancies needed to build the image but not to execute and run it.
Out of the 6 packages that used to install nginx, only two are necessary for running it.
We need to add those lines to our Dockerfile in the RUN
instruction in order to remove the unecessary packages.
apt-get remove build-essential \
libpcre3-dev \
zlib1g-dev \
libssl-dev \
-y && \
apt-get autoremove -y && \
apt-get clean && rm -rf /var/lib/apt/lists/*
Note : Splitting the removing instructions in two differents RUN
instructions will result in different layers in the final image.
A full featured Linux distribution like Ubuntu, Debian or Fedora.
It is built around musl
libc
and busybox
and is lightweight. Where the latest Ubuntu image weighs at around 28MB, alpine weighs 2.8MB.
Alpine is also secure and is a much better fit for creating containers than the other distributions.
Let's build our custom-nginx
using the Alpine image as it base.
The Dockerfile
would look like :
FROM alpine:latest
EXPOSE 80
ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"
ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
RUN apk add --no-cache pcre zlib && \
apk add --no-cache \
--virtual .build-deps \
build-base \
pcre-dev \
zlib-dev \
openssl-dev && \
tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} && \
cd ${FILENAME} && \
./configure \
--sbin-path=/usr/bin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--with-pcre \
--pid-path=/var/run/nginx.pid \
--with-http_ssl_module && \
make && make install && \
cd / && rm -rfv /${FILENAME} && \
apk del .build-deps
CMD ["nginx", "-g", "daemon off;"]
Few changes in the dockerfile explained as :
-
Instead of using
apt-get install
for installing packages, we use apk add. The--no-cache
option means that the downloaded package won't be cached. Likewise we'll use apk del instead of apt-get remove to uninstall packages. -
The
--virtual
option for theapk add command
is used for bundling a bunch of packages into a single virtual package for easier management. Packages that are needed only for building the program are labeled as.build-deps
which are then removed on line 29 by executing theapk del .build-deps
command. -
The package names are a bit different here. Usually every Linux distribution has its package repository available to everyone where you can search for packages. If you know the packages required for a certain task, then you can just head over to the designated repository for a distribution and search for it.
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
custom-nginx built ccc12d5008df 55 seconds ago 12.2MB
<none> <none> c048f5ceb3ce 17 minutes ago 85.3MB
custom-ngix packaged fafb482a6d08 6 hours ago 132MB
ubuntu latest 7e0aa2d69a15 4 weeks ago 72.7MB
alpine latest 6dbb9cc54074 5 weeks ago 5.61MB
fhsinchy/hello-dock latest f540930e8157 4 months ago 21.9MB
We can see how the image created with alpine is the most lightweight on all images.
Before we start coding the Dockerfile
the final output should be :
- The image should have Python pre-installed.
- It should contain a copy of my rmbyext script.
- A working directory should be set where the script will be executed.
- The rmbyext script should be set as the entry-point so the image can take extension names as arguments.
The steps to be taken in order to achieve what've been planned :
- Get a good base image for running Python scripts, like python.
- Set-up the working directory to an easily accessible directory.
- Install Git so that the script can be installed from fhsinchy GitHub repository.
- Install the script using Git and pip.
- Get rid of the build's unnecessary packages.
- Set rmbyext as the entry-point for this image.
Our Dockerfile
# set python as the base image, making it ideal for running python scripts usinf alpine variant python
FROM python:3-alpine
# set the default directory to zone/
WORKDIR /zone
# installs git & install rmbyext using git and pip and remove git aftewards
RUN apk add --no-cache git && \
pip install git+https://github.com/fhsinchy/rmbyext.git#egg=rmbyext && \
apk del git
# set the rmbyext as entry-point for this image
ENTRYPOINT [ "rmbyext" ]
Now let's build the image using the following command :
docker image build --tag rmbyext-alpine .
Let's run and test the image :
docker container run --rm -v $(pwd):/zone rmbyext-alpine jpg pdf
NO JPG FILES TO REMOVE.
Removing: PDF
arr.pdf
hello.pdf
To share images online, one need to create an account on at any of the online registries such Docker Hub. Once the account create, one can be able to connect through dthe ocker CLI by :
docker login
# enter username
# type password to successfully login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: alfahami
Password:
WARNING! Your password will be stored unencrypted in /home/fabric/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
In order to share an image online, the image has to be tagged as follow:
<docker hub username>/<image name>:<image tag>
Let's run it :
docker image build --tag alfahami/cutsom-nginx:latest --file Dockerfile .
Sending build context to Docker daemon 2.56kB
Step 1/7 : FROM alpine:latest
---> 6dbb9cc54074
Step 2/7 : EXPOSE 80
---> Using cache
---> 9584e3678c54
Step 3/7 : ARG FILENAME="nginx-1.19.2"
---> Using cache
---> 2bfb914d1cdc
Step 4/7 : ARG EXTENSION="tar.gz"
---> Using cache
---> 5a3ed0ab8188
Step 5/7 : ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
Downloading 1.049MB/1.049MB
---> Using cache
---> 4364fd836a36
Step 6/7 : RUN apk add --no-cache pcre zlib && apk add --no-cache --virtual .build-deps build-base pcre-dev zlib-dev openssl-dev && tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} && cd ${FILENAME} && ./configure --sbin-path=/usr/bin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-pcre --pid-path=/var/run/nginx.pid --with-http_ssl_module && make && make install && cd / && rm -rfv /${FILENAME} && apk del .build-deps
---> Using cache
---> 40c2689da973
Step 7/7 : CMD ["nginx", "-g", "daemon off;"]
---> Using cache
---> ccc12d5008df
Successfully built ccc12d5008df
Successfully tagged alfahami/cutsom-nginx:lates
In order to push to Docker Hub we use :
docker image push <image repository>:<image tag>
Which would be :
docker image push alfahami/cutsom-nginx:latest
The push refers to repository [docker.io/alfahami/cutsom-nginx]
96bc2c13d1a1: Pushed
1d756dc4e694: Pushed
b2d5eeeaba3a: Mounted from library/python
latest: digest: sha256:1c98877bb3e6b3ea2c38f8e8cf80c94ea768b238cd6edf7cef7f0a24cb7bc13a size: 950
Note : It should be custom instead of cutsom in the last build and push command. Anyway it doesn't matter.
Depending on the image size, the upload may take some time. Once it's done the image is to be found in your hub profile page.