Using these utility containers
as we did it here works.
But as I mentioned, it can be cumbersome to write
these long commands, especially with the bind mounts.
Good news is, we can also use Docker Compose for that
even though it's just one container.
But I did mention that Docker Compose
can also be helpful for just one container.
And maybe you also have projects with multiple containers,
some app containers, some utility containers,
you can mix and match that,
and you will see all of that in action in a bigger setup
and a bigger project right after this module.
when we dive into Level.
And there we'll set up a Level application
and also use some utility containers.
But, step-by-step, how can we use Compose here?
Well, as always, we have to add
a docker dash compose dot yaml file,
and in there we define our services as you learned it.
So we started with the version
which is 3.8 for me here,
and then I add my services key.
And here I have only one service and I will name it npm.
And this will be a container which should use node
and which should den also give me
this entry point and so on.
So I will use this Docker file here,
and hence in the npm service,
we can use to build command and simply use dot slash
to indicate that we're already in the folder
in which this Docker file can be found for this container.
So this now tells compose that this image should be built
when this container is being used.
Now, the cool thing is, we can also now add
this standard input open flag and the tdy flag
to set both to true,
to ensure that if the command needs our input,
we can provide that input.
And we can also now add our volumes here,
and then add our bind mount by connecting the folder
in which this docker compose dot yaml file is,
to the app folder inside of the container, just like this.
And that's essentially the command we executed before
now moved into a docker compose yaml file.
And there it's easier to maintain,
and we don't have to rewrite it all the time.
So now instead, we can simply use this docker compose file.
And we learned that we can use up
to bring up this container.
Now, if I just run up like this however,
it in the end does something strange.
It starts building npm,
and I don't know what it's doing there.
The problem here is that now I executed just npm,
because I have just npm as a entry point,
and I didn't specify any other command.
So instead we can use docker compose up
and then maybe also add a comment thereafter, maybe init.
But if I do that, that fails, no such service init.
And indeed, we use Docker Compose
differently than just a docker run command.
Docker compose up is really meant to bring up
services defined in a docker compose yaml file.
And here we're typically talking
about application containers,
so containers that are started
and then should continue running.
For these utility containers,
we also got to command though.
We get docker composed exec to run commands
in already running containers
which were created by Docker Compose,
but we also got docker compose run,
and that's now a useful command here.
Docker compose run allows us to run as single service
from this yaml file in case we had multiple services,
here we have only one, but if we had multiple services,
we could also target a single service by the service name.
So in this case, npm, because I used npm up here,
I use npm down there.
And then, with any command that should be upended
after our entry point of our choice,
so for example, init.
And now if I hit Enter,
I'm getting all these questions again,
and then it finishes and creates this project for me.
And that's even better to see if I delete node modules
and the package JSON files, and I run this again.
So let's run it again.
Let's quickly go through all these questions,
confirmed this, and here we are.
There's our package JSON file again.
So now we use docker compose for that,
with the docker compose run command.
Now one important word about that though,
if you inspect your running containers,
you'll see no containers, but if you inspect all containers,
you see a lot of containers here.
And the reason for that is, that I never added
the dash dash rm flag when I used docker run,
and of course we could do that there.
But for Docker compose we have something similar.
When we start services with docker compose up,
they are automatically deleted,
so the containers are automatically removed if we use down.
But with docker compose run, there is no up and down,
a container starts, does its thing,
and once the command finished, it shuts down.
But with run, it's not removed automatically.
You can change that though by not just using run like this,
but by also adding dash dash rm here,
and then this utility container will be removed
once to command finish.
So with that can still execute the command,
but thereafter this container is gone.
Of course for the moment we can clean up
all the containers we have with docker container prune,
and this will also remove all the unused containers.
But I find it quite important to be aware
of this dash dash rm flag on docker compose run,
because that makes sure that you don't end up
with all those unnecessary containers in the first place.
And that's it, these are utility containers
as I'd like to call them.