Working with Docker Images
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.
Overview of Dockerfile
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:
- FROM
- RUN
- CMD
- LABEL
- EXPOSE
- ENV
- ADD
- COPY
- ENTRYPOINT
- VOLUME
- USER
Many more....
COPY vs ADD Instruction
COPY and ADD are both Dockerfile instructions that serve similar purposes.
They let you copy files from a specific location into a Docker image.
Difference between COPY and ADD
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.
Use WGET/CURL wherever possible
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.
Step 1. Create Compressed file
root@dporwal-docker:~# touch compress.txt
root@dporwal-docker:~# tar -czvf compress.tar.gz compress.txt
root@dporwal-docker:~# docker build -t demobusybox .
Step 2. Create a Dockerfile and define the file to copy from to destination
vi Dockerfile
dockerfile1
Step 3. Run that Dockerfile
$ docker build .
Step 4. Verify the Output on the Destination directory.
Start the container that is build by DOcerfile
EXPOSE Instruction
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="porwal.deepak2000@gmail.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
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.
Commands:
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.
Exit Code | Description |
---|---|
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
command:
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:
https://docs.docker.com/engine/reference/run/#healthcheck
Dockerfile ENTRYPOINT
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"]
WORKDIR Instruction
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
Sample Snippet:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
Output = /a/b/c
ENV Instruction
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.
Example Snippet:
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
Example Snippet:
FROM busybox
ENV NGINX 1.2
RUN touch web-$NGINX.txt
CMD ["/bin/sh"]
References:
Official Docker
Udemy Course
Credit:
Zeal Vora
Top comments (2)
Please fix typo:
This syntax will change
ADD compress/tar.gz /tmp
toADD compress.tar.gz /tmp
.Thanks for this information 🙂