Posted on 2 Comments

Create single image layers with docker squash

Docker images consist of layers, a mechanism that will result in lower build time for your containers. A detailed article about how layers work on docker can be found in the below url.

https://vsupalov.com/docker-image-layers/

  • Each layer is an image itself, just one without a human-assigned tag. They have auto-generated IDs though.
  • Each layer stores the changes compared to the image it’s based on.
  • An image can consist of a single layer (that’s often the case when the squash command was used).
  • Each instruction in a Dockerfile results in a layer. (Except for multi-stage builds, where usually only the layers in the final image are pushed, or when an image is squashed to a single layer).
  • Layers are used to avoid transferring redundant information and skip build steps which have not changed (according to the Docker cache).

But what if you want to combine all the layers of an image into one single piece? This is why squash has been created.

How –squash works

Once the build is complete, Docker creates a new image loading the diffs from each layer into a single new layer and references all the parent’s layers. In other words: when squashing, Docker will take all the filesystem layers produced by a build and collapse them into a single new layer.

Build image without squash

docker build . -t test

Build image with squash

docker build . -t test1 --squash

In order to use squash command you will need to have experimental features enabled.

Navigate in docker desktop settings and in Windows (which is what I currently use) you should go on Docker Engine tab and change the experimental value to true.

After that you can run your docker command using —squash

Posted on Leave a comment

Run docker commands inside docker container

Considering that you have a docker container that runs an operating system, you could install docker inside it in order to use docker commands. Lets take for example the below Dockerfile. This will use the windows server core image and will install docker on it.

FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2022
RUN Invoke-WebRequest -UseBasicParsing https://download.docker.com/win/static/stable/x86_64/docker-20.10.18.zip -OutFile docker.zip; `
Expand-Archive -Force docker.zip -DestinationPath $Env:ProgramFiles; `
Remove-Item -Force docker.zip

As a result the administrator could execute docker commands by taking a prompt on the container. However not all commands will work if you do not perform the below volume binding. When you spin up a new container using the image that you created with the Dockerfile you should also use the below command. This way you could use docker commands like docker build, docker push etc. 

Windows

-v \\.\pipe\docker_engine:\\.\pipe\docker_engine

Linux

-v /var/run/docker.sock:/var/run/docker.sock
Posted on 1 Comment

Install python silently on Windows container and add to PATH

A container is a standard unit of software that packages up code and all its dependencies so the application runs quickly and reliably from one computing environment to another.

In this article we will examine how we can silently install python on a container running windows and add it to path. By doing so we can run python scripts inside our container and perform various tests, or even create webservices that will be hosted as containers inside a Cloud provider.

In order to host python inside a windows system I am using the below Dockerfile. A file named configuration.ps1 could exist inside your building directory and contain other instructions like modules installation. If you do not want this step you can remove the last two lines of the Dockerfile.

FROM mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2019
 RUN Invoke-WebRequest -UseBasicParsing https://www.python.org/ftp/python/3.10.7/python-3.10.7-amd64.exe -OutFile python.exe; `
    Start-Process python.exe -Wait -ArgumentList /PrependPath=1, /quiet; `
    Remove-Item -Force python.exe
COPY ./configuration.ps1 .
CMD .\configuration.ps1

When python is installed inside your container you will need to add it on PATH in order to use the verb python. This is done by appending the installation directory on windows PATH.

In order to do you will need to get an interactive session with your container.

docker exec -it container_name powershell

With the below command you can find where is the python installation located. You will need to change python version to the one that you installed. If you had installed the version 3.5 then you would need to change 3.10 to 3.5.

py -3.10 -c "import sys; print(sys.executable[:-10])"

The last step would be to set this location in the PATH. You can do that using the command below.

setx path "%path%;C:\Users\ContainerAdministrator\AppData\Local\Programs\Python\Python310\"

Then you can just press python and voilà.

Posted on 1 Comment

Pass secrets as ENV variables on docker build – Azure devops

Sometimes you may need not to store your environmental variables on your Dockerfile as they could contain secret values. Especially when using source control you do not want to commit your .env files that they may contain secrets and other sensitive information.

Using the below procedure you can inject secret values as ENV variables on your Dockerfile during the build. Its important to know that you cannot use –env-file with docker build command as it be only used with docker run.

docker run | Docker Documentation

docker build | Docker Documentation

On docker build you can pass –build-arg values in order to set build-time variables. These values don’t persist in the intermediate or final images like ENV values do. You must add --build-arg for each build argument.

In my scenario I wanted to commit an ENV variable permanently on the image but I wanted to avoid storing this value on source control. In more details I wanted to have the APP_KEY as ENV variable inside the container.

The first step was to set this as a secret on the Azure Devops pipeline.

Then you will need to create an ARG definition on the Dockerfile which value will be taken from the Devops pipeline run. Then this value will be passed to the ENV variable APP_KEY.

ARG APP_KEY
ENV APP_KEY=$APP_KEY

In the Docker command you will need to pass as –build-arg the values that you need (in my case APP_KEY)

    - task: Docker@2
      displayName: build docker image
      inputs:
        containerRegistry: 'registry'
        command: 'build'
        Dockerfile: '$(Pipeline.Workspace)/s/myapp/docker/Dockerfile'
        buildContext: '$(Pipeline.Workspace)/s/myapp'
        arguments: '-t image.azurecr.io/app-uat:${{parameters.dockertag}} --build-arg APP_KEY=$(APP_KEY)'