DEV Community

Cover image for Image Creation, Management, and Registry(Part 1)
Deepak Porwal
Deepak Porwal

Posted on • Edited on

Image Creation, Management, and Registry(Part 1)

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.

Dockerfile build

Overview of Dockerfile

Basic format of Dockerfile:

FROM busybox
COPY cat.txt
ADD add.txt
ADD compress.tar.gz /tmp
CMD ["sh"]
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Lets have a demo to show you how ADD work.

  1. Create a Compressed file
  2. Create a Dockerfile and define the file to copy from to destination
  3. Run that Dockerfile
  4. 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 .
Enter fullscreen mode Exit fullscreen mode

createCompressedfile

Step 2. Create a Dockerfile and define the file to copy from to destination

vi Dockerfile
Enter fullscreen mode Exit fullscreen mode

dockerfile1

Dockerfile

Step 3. Run that Dockerfile

$ docker build .
Enter fullscreen mode Exit fullscreen mode

Step 4. Verify the Output on the Destination directory.

Start the container that is build by DOcerfile

verifyOutput

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

inaccesible

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;"]
Enter fullscreen mode Exit fullscreen mode

This is my initial environment of my docker server.

inital stage

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 .
Enter fullscreen mode Exit fullscreen mode

build exposedemo

And here we will create a container from the exposedemo image we build.

docker container run -d exposedemo:0.0.1
Enter fullscreen mode Exit fullscreen mode

And in this image you can see in yellow box the container is running on port 9080

image

to Verify you can also use this command.

docker inspect exposedemo:0.0.1 
Enter fullscreen mode Exit fullscreen mode

verifyexpose

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)
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

We will get the IP Address of this container to connect.

docker inspect demohealthcheck 
Enter fullscreen mode Exit fullscreen mode

demohealthcheck

Now lets create dockerfile and implement HEALTHCHECK command

FROM demohealthcheck
HEALTHCHECK --interval=5s CMD ping -c 1 172.17.0.3
Enter fullscreen mode Exit fullscreen mode

healthcheckdockerfile

Building image and container from the above docker file and check the connection.

monitoringimage

We can also check the HEALTHCHECK Logs by

docker inspect monitor
Enter fullscreen mode Exit fullscreen mode

inspectmonitor

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
Enter fullscreen mode Exit fullscreen mode

and we will see that container is unhealthy.On doing docker inspect tmp we found that curl command is not found.

unhealthycontainer

curlcommandnotfound

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
Enter fullscreen mode Exit fullscreen mode

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"]
Enter fullscreen mode Exit fullscreen mode

CMD Command

entrypoint

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']
Enter fullscreen mode Exit fullscreen mode

workdircmd

The WORKDIR instruction can be used multiple times in a Dockerfile

Sample Snippet:

WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
Enter fullscreen mode Exit fullscreen mode

Output = /a/b/c

Exampleabove snippet

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
Enter fullscreen mode Exit fullscreen mode

envcommand

implementation of ENV in dockerfile

Example Snippet:

FROM busybox
ENV NGINX 1.2
RUN touch web-$NGINX.txt
CMD ["/bin/sh"]
Enter fullscreen mode Exit fullscreen mode

envdockerfile

References:
Official Docker
Udemy Course

Credit:
Zeal Vora

Prev: Getting Started with Docker

Next: Image Creation, Management, and Registry(Part 2)

Top comments (2)

Collapse
 
peter279k profile image
peter279k

Please fix typo:
This syntax will changeADD compress/tar.gz /tmp to ADD compress.tar.gz /tmp.

Collapse
 
dporwal profile image
Deepak Porwal

Thanks for this information 🙂