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.
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 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.
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:
- path: ./go.mod
- path: ./main.go
- path: ./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 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
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
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
main.css, they are synced with the container. When I modify
go.mod the image is rebuilt, and the container is restarted. Try it
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.