Recently Docker brought some new stuff that I found very useful for developers. They are still in the experimental phase but are already very useful. Try them and give your feedback to the Docker team. The code I’m using for this is available here.
Let’s start…
Init
Writing a Dockerfile when starting with a new application is tedious. Why? Because we are repeating most of the stuff over and over again. So, in the
end, we reach to copy/paste solution. Of course, copy/paste needs to be modified to fit an application’s needs. I do not say that copy/paste is terrible, but with it,
we miss new stuff that Docker brings to us. Even seasoned developers miss stuff. If we do not do it every day, we forget. Because of that, the Docker team brought
us a new command called init
. The init
is not new but is still in beta. This time with more improvements.
It is a straightforward command that will create a Dockerfile for us. It asks a few questions, and based on our answers, it will create a Dockerfile. Let us see how it works:
It is effortless to use. Initially, when the Docker team introduced it, only Go was supported. With the latest release(docker desktop 4.19.0 and docker engine v23.0.5)
docker init
supports NodeJS and Python, too. I’m sure that they will add more languages in the future.
If you inspect the Dockerfile, you will see that it tries to be simple but also includes all the best practices when writing a Dockerfile. It will try to use cache and multi-stage builds. You can go with generated Dockerfile as is. I prefer to modify it a bit. I suggest you compare my Dockerfile version with generated one. I like Google’s distroless images. In my example, I’m also serving static files, so I need to add them to Dockerfile.
Watch
If you look at the compose.yaml
file, you will see nothing exciting. Nothing new or fancy. But there is something new.
When you are working with docker compose
and want to run your changes, you need to rebuild the image. So, every time you do something like this:
docker compose -f <compose file> up --detach --build <service name>
But what if you do not need to do it anymore? What if docker compose
can do it for you? Well, it can. And it can do things to rebuild your app only when
needed or to update static files. In my example, I have a Go server that serves one static file. When I change the code, I need to rebuild the image. But when I
change static files, I want to be updated. See:
services:
server:
build:
context: .
target: final
ports:
- 8080:8080
x-develop:
watch:
- path: ./go.mod
action: rebuild
- path: ./main.go
action: rebuild
- path: ./static/
action: sync
target: /app/static/
The section under x-develop
with the name watch
does all the magic. That is an experimental feature. It has two actions
that can be used: rebuild
and
sync
. The rebuild
will rebuild the image, and the sync
will sync files from the host to the container.
In the example above, I instruct docker compose
to watch for the changes in the go.mod
and main.go
files and rebuild the image when they change. While if there
are any changes in a directory with the name static
(notice the trailing slash), sync them to the container. The target
specifies where to sync files in the
container. In my case, I want to sync them to the /app/static/
directory.
As this feature is experimental, it will not work if you just run docker compose up -d
. First, run docker compose up -d
, and run docker compose alpha watch
when
all containers are up and running. That will start watching for changes. If you want to stop watching, press Ctrl+C
. Let’s see this in action:
Initially, I built and ran a container with docker compose up -d
. Then I run docker compose alpha watch,
and instruct docker compose
to watch for changes. When I
modify index.html
or main.css
, they are synced with the container. When I modify main.go
or go.mod
the image is rebuilt, and the container is restarted. Try it
out yourself.
If you find this helpful feature, please leave your feedback and suggestions here.
Other noticeable stuff
With 4.19.0 release, the Docker engine and CLI are updated to Moby 23.0.
That brings a lot of new stuff. One of the things that can be confusing on start is that docker build
is now an alias for docker buildx build
. The reason is that
Buildx and BuildKit are default builders on Linux and OSX. You will notice differences when building images. You’ll see switching blue and white
lines in the short demos above. White lines are tasks in progress, while blue ones are completed tasks. As well you’ll see that Buildx is trying to run tasks in parallel.
Enjoy!