Every Docker container is based on an image.
Till now we have been using images that were created by others and available in Docker Hub.
Docker can build images automatically by reading the instructions from a Dockerfile
A Dockerfile is a text document that contains all the commands a user could call on the command line to assemble an image.
Basic format of Dockerfile:
FROM busybox COPY cat.txt ADD add.txt ADD compress.tar.gz /tmp CMD ["sh"]
A Dockerfile must start with a FROM instruction.
The FROM instruction specifies the Base Image from which you are building.
There are multiple INSTRUCTIONS that are available in Dockerfile, some of these include:
COPY and ADD are both Dockerfile instructions that serve similar purposes.
They let you copy files from a specific location into a Docker image.
COPY takes in an src and destination. It only lets you copy in a local file or directory from your host
ADD lets you do that too, but it also supports 2 other sources.
First, you can use a URL instead of a local file/directory. Secondly, you can extract a tar file from the source directly into the destination.
Using ADD to fetch packages from remote URLs is strongly discouraged; you should use curl or wget instead.
This will execute all the lines repeatedly, will execute everytime same file. So, its not a good practice
ADD http://example.com/big.tar.xz /usr/src/things/ RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things RUN make -C /usr/src/things all
This will not create unnecessary files and will make a sequence, which will deal with only file file and then process.
RUN mkdir -p /usr/src/things \ && curl -SL http://example.com/big.tar.xz \ | tar -xJC /usr/src/things \ && make -C /usr/src/things all
Lets have a demo to show you how ADD work.
- Create a Compressed file
- Create a Dockerfile and define the file to copy from to destination
- Run that Dockerfile
- Verify the Output on the Destination directory.
root@dporwal-docker:~# touch compress.txt root@dporwal-docker:~# tar -czvf compress.tar.gz compress.txt root@dporwal-docker:~# docker build -t demobusybox .
$ docker build .
Start the container that is build by DOcerfile
The EXPOSE instruction informs Docker that the container listens on the specified network ports at runtime and it does not actually publish the port. It functions as a type of documentation between the person who builds the image and the person who runs the container, about which ports are intended to be published.
In above dockerfile1 you can see the scenario where person will not be able to get the port it should intends to publish because of not using EXPOSE command
So, now we will use this EXPOSE command Dockerfile.
Here I'm creating a dockerfile, which will launch nginx server on port 9080.
FROM ubuntu:latest LABEL version="0.0.1" LABEL maintainer="email@example.com" RUN apt-get update && apt-get upgrade -y RUN apt-get install nginx -y EXPOSE 9080 CMD ["nginx", "-g", "daemon off;"]
This is my initial environment of my docker server.
Now we will run below commands to build the custom image exposedemo with tag 0.0.1
docker image build --tag exposedemo:0.0.1 .
And here we will create a container from the exposedemo image we build.
docker container run -d exposedemo:0.0.1
And in this image you can see in yellow box the container is running on port 9080
to Verify you can also use this command.
docker inspect exposedemo:0.0.1
HEALTHCHECK instruction Docker allows us to tell the platform on how to test that our application is healthy.
When Docker starts a container, it monitors the process that the container runs. If the process ends, the container exits.
That's just a basic check and does not necessarily tell the detail about the application.
We can specify certain options before the CMD operation, these includes:
HEALTHCHECK --interval=5s CMD ping -c 1 172.17.0.2 --interval=DURATION (default: 30s) --timeout=DURATION (default: 30s) --start-period=DURATION (default: 0s) --retries=N (default: 3)
Lets create a container demohealthcheck which we will be using to check the connection, and will create another container monitor where we will implement HEALTCHECK command by checking connection with demohealthcheck container.
docker container run -dt --name demohealthcheck busybox sh
We will get the IP Address of this container to connect.
docker inspect demohealthcheck
Now lets create dockerfile and implement HEALTHCHECK command
FROM demohealthcheck HEALTHCHECK --interval=5s CMD ping -c 1 172.17.0.3
Building image and container from the above docker file and check the connection.
We can also check the HEALTHCHECK Logs by
docker inspect monitor
if ExitCode: 1 then, there is something wrong with container.
|0: Success||the container is healthy and ready to use|
|1: Failure||the container is not working correctly|
|2: Reserved||do not use the exit code|
We can also use HealthCheck commands while building the container.
like below we are using --health-cmd
docker run -dt --name tmp --health-cmd "curl -f http://localhost" busybox sh
and we will see that container is unhealthy.On doing docker inspect tmp we found that curl command is not found.
Now we will remove this container and will try to check the container after every 5 sec and it will retry 1 time on failure.
you can try below command and let me know in discussion if you are good to do so.
docker run -dt --name tmp --health-cmd "curl -f http://localhost" --health-interval=5s --health-retries=1 busybox sh
for more commands you can check:
The best use for ENTRYPOINT is to set the image’s main command
ENTRYPOINT doesn’t allow you to override the command.
It is important to understand the distinction between CMD and ENTRYPOINT.
As, CMD command in Dockerfile can be overridden by runtime command. Whereas ENTRYPOINT command will append to the given command given at runtime.
Sample Code Snippet:
FROM ubuntu ENTRYPOINT ["top", "-b"] CMD ["-c"]
The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile
FROM busybox RUN mkdir /root/demo WORKDIR /root/demo RUN touch dporwal.txt CMD ['/bin/sh']
The WORKDIR instruction can be used multiple times in a Dockerfile
WORKDIR /a WORKDIR b WORKDIR c RUN pwd
Output = /a/b/c
Passing as argument during run time.
The ENV instruction sets the environment variable to the value .
You can use -e, --env, and --env-file flags to set simple environment variables in the container you’re running or overwrite variables that are defined in the Dockerfile of the image you’re running.
docker run --env VAR1=value1 --env VAR2=value2 ubuntu env | grep VAR Eg. docker run -dt --name env01 --env USER=USERADMIN busybox sh
implementation of ENV in dockerfile
FROM busybox ENV NGINX 1.2 RUN touch web-$NGINX.txt CMD ["/bin/sh"]