Docker concepts you should know
Published: 2022-02-11 12:21:35

#Difference between image and container

You need to feel difference between docker "image" and "container".
Make sure you know understand the flow:
You have Dockerfile to build image you need to run containers. 

[![docker flow](https://mermaid.ink/img/pako:eNpNjT0LAjEQRP9K2MLqrtAyhY1aCFbaplmTzV0wH7JuEDnuvxsORbt5Mw9mAlscgQYfy9OOyKJOZ5P3xd6IfYik-l65hdS1hugab9Ux4fC_cM1LvytZMGTitVr9YAMdJOKEwbWjyWSlDMhIiQzoFh15rFEMmDw3td4dCh1ckMKgPcYHdYBVyuWVLWjhSl9pH3BgTB9rfgNciEU6)](https://mermaid.live/edit#pako:eNpNjT0LAjEQRP9K2MLqrtAyhY1aCFbaplmTzV0wH7JuEDnuvxsORbt5Mw9mAlscgQYfy9OOyKJOZ5P3xd6IfYik-l65hdS1hugab9Ux4fC_cM1LvytZMGTitVr9YAMdJOKEwbWjyWSlDMhIiQzoFh15rFEMmDw3td4dCh1ckMKgPcYHdYBVyuWVLWjhSl9pH3BgTB9rfgNciEU6)
 
#Docker file build contexts

You need to understand the context of each line of dockerfile

* what is the current build context (directory on agent)
* what is the current working directory on image
* what is the current user 
* what is the current stage (for multistage build)
* how it affects layer cache

Agent is a machine where `docker build` command started. `docker build` command has required parameter "build context" which is folder on agent machine. 
For example, the `COPY <src> <dest>` command `<src>` parameter is path relative to the current build context folder. 
`<dest>` parameter is path relative to the current working directory on image file system.

For example this [Dockerfile ](https://github.com/musukvl/docker-concepts-you-should-know/blob/master/src/webapi/Dockerfile) has the following file systems:
```
WORKDIR /src
COPY . .
```
<table>
  <tr>
     <td>Build context (agent)</td>
     <td>Work directory (image)</td>
  </tr>
  <tr>
     <td>
       <pre>
- docker-concepts-you-should-know
  - src
    - WebApi
      - WebApi.csproj
      - Program.cs
      - Dockerfile
       </pre>
     </td>
     <td>
       <pre>
- src
  - src
    - WebApi
      - WebApi.csproj
      - Program.cs
      - Dockerfile
       </pre>
     </td>
  </tr>   
</table>


#Build time and Runtime

You are able to run apps while `docker build` building image with `RUN` statement. And you can run your apps in running container with `ENTRYPOINT` or with `docker exec`. Normally you might need to run your development tools build time, but your service or utils (like database migration) in runtime.
Build time executions are focused on image content, for example you might want to build binaries from source code. Build time you don't have your private network and volumes, so you can't have access to database. 

#Layout caching

Each statement in docker file produces image cache layer on docker host machine. 
Cache layers could help application build time, for example 
`dotnet restore` result will be cached if files copied to the docker image are the same. That is why default [Dockerfile ](https://github.com/musukvl/docker-concepts-you-should-know/blob/master/src/webapi/Dockerfile) generated by visual studio copies csproj files first, and other files only after dotnet restore. 
```
WORKDIR /src
COPY ["src/webapi/webapi.csproj", "src/webapi/"]
RUN dotnet restore "src/webapi/webapi.csproj"
COPY . .
```
Andrew Lock wrote excellent article about this optimization.
https://andrewlock.net/optimising-asp-net-core-apps-in-docker-avoiding-manually-copying-csproj-files/

#Docker-compose

Docker compose calls Docker under the hood. But docker-compose has it's own behavior and some commands could work differently.

#Entrypoint
You can use shell script as Entrypoint. If you have windows developer environment you need to remember:

1. Set lr for .sh files in .gitattributes
```
*.sh text eol=lf
```
2. Set +x for .sh file in git metadata
```
git update-index --chmod=+x foo.sh
```
or you can use [TortoiseGit](https://tortoisegit.org/):