Docker

The main intention behind writing this blog is to understand docker instructions and it’s capabilities while writing a Dockerfile.

In the recent past it’s hard to find an application without a Dockerfile. 😃

  • INSTRUCTIONS used in Dockerfile
    • FROM
    • MAINTAINER
    • RUN
    • CMD
    • LABEL
    • EXPOSE
    • ENV
    • ADD
    • COPY
    • ENTRYPOINT
    • VOLUME
    • USER
    • WORKDIR
    • ARG
    • ONBUILD
    • STOPSIGNAL
    • HEALTHCHECK
    • SHELL

FROM

FROM <image>                # picks latest by default
FROM <image>:<tag>          # specific version can be pulled
FROM <image>@<digest>       # This makes sure we pull the specific image with provided digest, 
                            # If image content is changed digest also changes.
  • FROM cmd can be used multiple times in the same Dockerfile to build multiple images. This generates unique Id for each image.

    FROM alpine:3.5
    FROM python
    FROM vineeth97/saanvidashboard@sha256:ff6893d0750268ecfcdbe1e4a4d6f70b1a2ef43c5054ff11da0d5bc3595a79ec
    

MAINTAINER

MAINTAINER

  • This is deprecated as docker LABEL instruction does exactly the same.

    FROM alpine
    MAINTAINER vineeth
    

LABEL

LABEL ABC=“XYZ” DEF=“MNO” LABEL ABC=“XYZ”
DEF=“MNO”
GHI=“PQR”

  • The LABEL cmd adds metadata to an image. A LABEL is a key-value pair.
  • If same key has different values the last occurring will take the precedence.

    FROM alpine:3.3
    LABEL fruit="APPLE" \
      vegetable="TOMATO" \
      fruit="BANANA"
    LABEL abc="DEF" hjk="PQR"
    

RUN

RUN ["npm","start"]   # exec form
RUN npm start         # shell form

Difference between shell form and exec form. By default shell form executes the commands in /bin/bash -c context But exec form needs explicit context to be set. As it doesn’t pick /bin/bash -c by default.

FROM ubuntu
RUN apt-get update -y
ENV myName="John Doe" myDOg=Rex\ The\ Dog \
        myCat=fluffy
ENTRYPOINT ["/bin/bash","-c","echo $myName"] or ENTRYPOINT echo $myName

The above docker instrctions are combination of shell and exec form in the ENTRYPOINT instruction.

CMD

CMD ["executable","param1","param2"] (exec form this is preferred form)
CMD ["param1","param2"] (used to provide default parameters to ENTRYPOINT])
CMD <command> <param1> <param2>
  • CMD is used to provide a instruction to Dockerfile which also can overwritted using docker run cmd, Also used to provide defaults to the ENTRYPOINT cmd this defaults are also overwritted using docker run cmd .

ENTRYPOINT

  • Difference between CMD and ENTRYPOINT, CMD is used only once if it’s provided multiple times last provided one will take precedence. CMD is overwritted when we pass any command with docker run IMAGENAME XYZ ENTRYPOINT is used as the command which cannot be overwritten. But we can append parameters to the ENTRYPOINT either by CMD after ENTRYPOINT in Dockerfile or else by passing from docker run command.

    FROM ubuntu
    ENTRYPOINT ["echo"]
    CMD ["VINEETH"]
    

In the above docker instruction CMD instruction is taken by default if any string is provided with docker run IMAGENAME AQUA will override the default CMD. If no CMD is provided. Any command provided with docker run will be appended to ENTRYPOINT command.

SHELL

  • The SHELL instruction is particularly used on windows. where there are two commonly used and quite different native shells: CMD and POWERSHELL. as well as alternate shells available including sh.
  • The SHELL instruction can be used multiple times. But the previous SHELL instruction is ignored and current SHELL instruction affects all the subsequent instructions.

    FROM microsoft/windowsservercore
    
    # Executed as cmd /S /C echo default
    RUN echo default
    
    # Executed as cmd /S /C powershell -command Write-Host default
    RUN powershell -command Write-Host default
    
    # Executed as powershell -command Write-Host hello
    SHELL ["powershell", "-command"]
    RUN Write-Host hello
    
    # Executed as cmd /S /C echo hello
    SHELL ["cmd", "/S", "/C"]
    RUN echo hello
    
    

HEALTHCHECK

  • HEALTHCHECK instruction is used to check the health of the container based on some validations. This lets us know whether the container is not only just up and running but also serving the requests as intended.

    FROM node:latest
    COPY ./ ./app
    EXPOSE 4200
    WORKDIR /app
    RUN npm install
    #STOPSIGNAL SIGKILL
    #HEALTHCHECK CMD sleep 50
    HEALTHCHECK --interval=1s --timeout=1s --retries=1 CMD curl --fail http://localhost:4200/ || exit 1
    CMD ["npm","start"]
    

–interval is used to check for time interval in checking the health –timeout is used to limit the timeout for each check –retries set retries to confirm unhealthy upon specific consecutive failures

STOPSIGNAL

  • STOPSIGNAL instruction is used to pass a signal to the container when we try stopping the container with docker stop it executes SIGTERM (this gives the graceful time to terminate the process if not it will kill the process) and docker kill executes SIGQUIT or SIGKILL.

    FROM ubuntu
    STOPSIGNAL SIGKILL
    CMD ["sleep","5000"]
    

ADD

  • ADD instruction is used same as COPY instruction but it has some additional functionalities such as ADD from remote URL, extracting the tar from the host machine to docker image during build without multiple instruction which in return creates the multiple layers besides from this functionalities it also does all functionalities COPY instruction does.

    FROM ubuntu
    RUN mkdir node
    ADD node-v8.10.0-linux-x64.tar.xz /node
    ADD https://nodejs.org/dist/v8.10.0/node-v8.10.0-linux-x64.tar.xz .
    CMD ["sleep",5000"]
    

COPY

  • COPY instruction is used to copy data from host machine to container. With COPY instruction we specify the src and destination.

    FROM ubuntu
    COPY . .
    CMD ["sleep","5000"]
    

ENV

  • ENV instruction is used to pass the environment varibales to the container runtime. It works same as environment variables in host level.

    FROM ubuntu
    ENV myName="John Doe" myDOg=Rex\ The\ Dog \
        myCat=fluffy
    ENTRYPOINT ["/bin/bash","-c","echo $myName"]
    

ARG

  • ARG instruction is used to pass dynamic values during docker build with docker build –build-arg VALUE=1.0
  • ARG instruct can optionally contain default value if no value is passed during docker build.
  • When both ARG and ENV is used with same name ENV will override the ARG.

    FROM ubuntu
    ARG app=nodejs
    RUN apt-get update && apt-get install -y $app
    CMD ["sleep","5000"]
    

Above ARG instruction can we overrided during the build time using docker build –build-arg app=python . In the above docker instructions app = nodejs, But this can be overrided using docker build.

ONBUILD

  • ONBUILD instruction is used to perform an action on the image which uses it as base image. Triggers are inherited by the “child” build only. In other words, they are not inherited by “grand-children” builds.
  • The ONBUILD instruction may not trigger FROM, MAINTAINER, or ONBUILD instructions.

    FROM ubuntu
    ONBUILD RUN mkdir VINEETH
    

The above docker image will create VINEETH directory to all the images which use the above image as base image. i.e Build the above image using

docker build -t vineeth  .

This image on build will perform the action which is mentioned in the base image with ONBUILD instruction. i.e

RROM vineeth

WORKDIR

  • WORKDIR instruction is used to predefine the current directory in which build CMD, RUN instructions needs to be executed on. Even when we bash into the container we get into the WORKDIR by default.

    FROM ubuntu
    RUN ["mkdir","sample"]
    WORKDIR sample/
    ADD https://nodejs.org/dist/v8.10.0/node-v8.10.0-linux-x64.tar.xz .
    CMD ["sleep","5000"]
    

USER

  • USER instruction is used to set the default user to the container and this gets validated and impacted when we run the container. Even if a user is invalid build succeeds. This instruction teakes action during docker run step.

    FROM ubuntu
    RUN useradd -ms /bin/bash  vineeth
    USER vineeth
    CMD ["sleep","500"]
    
    

Tips

  • During docker build the docker cli tries sending the entire content of Dockerfile directory to the docker daemon to increase the build’s performance, exclude files and directories by adding a .dockerignore file to the context directory.
  • Starting with version 18.09, Docker supports a new backend for executing your builds that is provided by the moby/buildkit project. The BuildKit backend provides many benefits compared to the old implementation. To use the BuildKit backend, you need to set an environment variable DOCKER_BUILDKIT=1 on the CLI before invoking docker build.