Check out a free preview of the full Complete Intro to Containers, v2 course
The "Docker Compose Project" Lesson is part of the full, Complete Intro to Containers, v2 course featured in this preview video. Here's what you'd learn in this lesson:
Brian uses Docker Compose to create a project with three container servers: An API, a database, and a static Nginx web server. Docker Compose builds and runs each container. The nodemon package is added to the project, so the server will restart from within the container when the server code is modified.
Transcript from the "Docker Compose Project" Lesson
[00:00:00]
>> Brian Holt: Let's go ahead and do a project, it's gonna be heavily based on what we did before with like the adding files to a Mongo database and the volumes project that we did and very similar to something like that. It's now we're going to be using Docker compose to manage the Mongo database and the networking, and we're also gonna add a front end using React, Parcel, and then Nginx ultimately to solve it.
[00:00:26]
So we'll have three services, an API, the web front end service, and the database service. Now you and I could code this together. It's not a particularly interesting project in the sense that I don't think it's very interesting. So here in the project files for Complete Intro to Containers v2, there's a directory called Docker Compose.
[00:00:46]
We're just gonna copy that entire project over and then we'll give a little overview of what's in the project. So I'm gonna go to my desktop again and I'm gonna copy -R and personal,
>> Brian Holt: And that is containers-projects. And we want the docker-compose. And we'll just call it docker-compose again because that's easy.
[00:01:20]
>> Brian Holt: So I'm gonna go into Docker Compose. So, again, I just copied this directory right here, you can actually just do it directly in the directory there. That's totally fine. Okay, and let's go through a little tour of the code here. Close that.
>> Brian Holt: We'll talk about the Docker-Compose file here in just a second, but in the interim, I just wanna show you what's actually in the project.
[00:01:50]
This index file, it's a slightly modified version of that Mongo app that we were looking at before. One of the things is we did add cores because we're gonna be listening on two different ports and Firefox and Chrome don't like that. You get cores errors when you do that.
[00:02:06]
But beyond that, I think this is almost exactly the same. Okay, same package.json except we added a cores handler for Fastify. So that's the API service. Nothing interesting there and then the web service. You can see this is just a parcel project built with React and react.dom. Okay, there's a little Docker file here that just it's a two stage build.
[00:02:34]
It builds a node and then it serves it from nginx. So, nothing too interesting there. There's an index file, there's a style file, and there's a web.jsx file. And this is just a little React app that has a button that every time you click the button, it calls the API, and then it gets back from the API whatever, however many items are in the database.
[00:03:00]
Okay, so that is all of the code that we're doing. I even committed the dist directory for you so that you don't actually have to go and build the project yourself. But if you wanted to, all you do is npm run, build. That's it, okay. So let's talk about docker-compose now.
[00:03:23]
We now have three services in here. As you might imagine, a service is like micro-services, like the thing that Netflix cursed us all with. That's what all of this is, we have API Which is going to be that API service that we talked to about the build API that's referring to the this is coming from the API directory.
[00:03:47]
So when if I ask docker-compose to build my project for me, it knows where to find the Docker file, which is going to be in the API directory. I'm telling it to expose port 8080 and make them available locally for me. So if I want to call the API directly, I can and it's saying links db.
[00:04:08]
This is basically just saying that it talks to the db service on the network. So make that available to the API service, and then we're giving it the environmental variable of how to connect to Mongo. The database service is really just like, hey, just run mongo:7 directly off Docker Hub, no modifications.
[00:04:32]
That's all that does. And then the web service, build from web this is the API_URL. And the port's nginx by default exposes port 80 but we wanna make it available on port 8081. Yeah, question.
>> Speaker 1: As soon as an applied network created for these containers is by using docker-compose.
[00:04:55]
>> Brian Holt: Which docker-compose totally manages for you.
>> Speaker 1: Why is there no links from the web Web to the API?
>> Brian Holt: Because it's all done through your browser, right? So the nginx container is not speaking to the API, right? Nginx doesn't call the API, your browser calls the API.
[00:05:18]
So we have to expose this because Because your front end client is gonna call api 8080, right? But if they did, right, let's say if you had some sort of heartbeat or something like that, you would have to do that, right? But there's no network traffic between the two of them, I guess that's the sum of the story.
[00:05:38]
Whereas these two do have network traffic between each other. So, let's run it, right? We're gonna come into our CLI, and I'm gonna say docker compose up -- build. You do need the -- build or it's just going to assume it's like, you already built these for me.
[00:06:06]
So I almost always end up putting it on there because I usually want it to build it for me.
>> Brian Holt: So you can see now it is running multiple containers here, where is the. So, there it is. Okay, so you can see web-1, this is all the logs coming from Nginx, right?
[00:06:30]
Web being the name of the container that we called it, right? And -1 being the first replica of there, because you can actually tell us like, hey, please run ten of these for me or run 100 of these for me, right? We're just going to say run one of each at the moment.
[00:06:43]
We have db-1, as you might imagine, that's the Mongo-1 that's taken care of. And then somewhere down here we have API, which I'm sure it'll be somewhere. Maybe one I'm sure if we make a request to it. localhost 8081.
>> Brian Holt: Yeah, right there, API. I have this attached to Yvonne, so I've been running this for a little bit already.
[00:07:14]
That's why I have 14 counts in here. But if I click Add, it should add new things to my database. So now I have 28 records in my database.
>> Brian Holt: And that's connecting the API to the back end right. So if I look at my network traffic here, it is connecting to localhost:8080 and you can see, does this tell you that it's coming from Fastify.
[00:07:43]
Nope, it doesn't but you can see that that access control header is coming in that we did. And then if we look at this, we can definitely tell that this is coming from Nginx, It should tell you that.
>> Brian Holt: Right there, document. Yeah, Server from Nginx.
>> Brian Holt: Another kind of cool thing about this is like, because I didn't expose Mongo, Mongo's not technically on the public network, right?
[00:08:12]
It's enclosed into my Docker network. So in theory, you could get into the API service and then use that to call Mongo, but It's not available on the public Internet, which is cool. It's only available on my local Mongo or sorry, on my local Docker network, just for for funsies.
[00:08:31]
I'm going to stop this and it'll take just a second. What if we wanted to have more than one container running, right? That's one of the advantages of containers that it's really easy to scale them up and scale them down because they're cattle, right? They're easy to replicate.
[00:08:50]
I did not write the API service in such a way that it's easy to scale, so we're not gonna scale that one. You could say docker-compose up and then I can say --scale web=10, and this will create ten of my web service.
>> Brian Holt: And I probably the same thing here I'm probably listening on the same port.
[00:09:17]
I am listening to the same port. Yeah, this won't work at the moment because I've specifically tied it to one port and I don't have something in front of it. So that's actually not gonna work but you probably could do DB maybe. Yeah, so look at this. I now have db-3, I have db-9, right?
[00:09:44]
And so I actually have of ten my Mongo running in the background. So if I say docker ps at the moment, you can see I have, does it tell me the names? Where is the names?
>> Brian Holt: It doesn't, but that's fine. You can see I have the DB there, but all these different ones, yeah, right there, docker compose web, docker compose db-3, docker compose db-9, db-7.
[00:10:19]
So Docker compose does have the ability to scale up and scale down as well with those flags.
>> Speaker 2: With the scale are those fully individual Mongo instances? So it's everything in that Mongo instance every time.
>> Brian Holt: That's me based on your configuration you can do things that are like striping and sharding and things like that.
[00:10:45]
I think by default, I haven't set up anything right. I didn't give it any configuration. So my guess is that there are 100%, one to one redundant. So you'd have one primary which I think if I remember how Mongo works at It's done by election, so they're gonna elect their own primary node and then everything else would be a secondary node.
[00:11:06]
I don't know, Mongo has eventual consistency, so eventually you might be able to send writes to secondaries and they'll propagate it to the primary and then it'll propagate back. But it's been a while since I've used Mongo. I work at a database company, so I tend to use mine.
[00:11:21]
[LAUGH] And before that, I worked at a database company, so I used to use that one. But when I was at my first company, we used a lot of Mongo, and then Reddit, we used MySQL. So yeah, it's been a while since I've used Mongo professionally. So hopefully you're seeing some of the value of docker-compose.
[00:11:44]
In particular, I showed you how to do like dev containers and all that kind of stuff. You can put a Docker compose in there as well. So let's say your particular development environment requires a database and a couple of services running. Docker compose can handle all of that for you for your local development environments as well.
[00:12:02]
But when I'm writing stuff that requires multiple things running, I always use Docker compose. It's a very, very useful feature for for Docker
Learn Straight from the Experts Who Shape the Modern Web
- In-depth Courses
- Industry Leading Experts
- Learning Paths
- Live Interactive Workshops