#100DaysOfWeb in Python Transcripts
Chapter: Days 97-100: Docker and Docker Compose
Lecture: Docker image for our Python services
Login or
purchase this course
to watch this video and the rest of the course contents.
0:00
It's time to move over and get our Python-backed services running in another container. Now, you know what? It's going to be a lot like this one.
0:10
Same, this is all the same. We're not going to use Nginx, so we're not doing that little bit. But from here on is going to be the same.
0:21
Let me duplicate that for a minute and then we'll go back and fix this to make it a little bit better. So we'll create a Dockerfile here
0:29
and we can go ahead and add those little utilities I like. Like I said, if you want, take 'em out, it's no problem.
0:34
But we're not doing any of that stuff. What we're going to do is we're going to copy a movie_svc like so to /app. That should be good.
0:44
I'm going to also go and create a virtual environment. Do you have to do this in a Docker container?
0:50
No. It's kind of completely dedicated to just this app. But for example, like, this uses Python also is going to mess with the global environment.
1:00
So what I'd like to do is have something a little bit more isolated. So I'm going to come over here and I'm going to try
1:07
to put my copy as late as possible 'cause those files are going to change as I work on my app. All this other stuff can cache much, much more often.
1:15
So what we're going to do is we're going to create a virtual environment. Now, we're also going to need a few other things up here at the beginning.
1:23
We're going to need some Python tools like we need Python-pip and Python-dev and build-essentials, so we're going to add that in here.
1:31
And then we're going to run a command which is going to be Python -m venv /venv. So it's going to create a virtual environment
1:43
right in the root of our system. Now remember, when you create virtual environments they get out of date immediately, right?
1:52
They for some reason come with an out-of-date pip. Like, this step doesn't bother to upgrade it even if it's somewhere else on the system.
2:00
So the next thing we want to do is we're going to make sure our virtual environment has the latest pip. So we'll just say this in /venv
2:07
normally you would say source or we need to run the full path and that works out better for Docker. So /venv/bin/pip install -U pip setuptools
2:22
Let's go and see how this runs. So we're over here in our services and we're going to run Docker build this directory
2:33
see what we get. See how a bunch of this was already cached? Great, here's our Python-dev and pip and all that that we're installing on the system.
2:52
Oh, I forgot, we're going to need do Python3, okay? So we need to make sure that we have this installed but Python, I guess, means Python 2.
3:03
Try again. There we go, that's much better. That's cool, we're only 10 versions out of date on pip. But not anymore, okay.
3:18
So our virtual environment is all set up. What else do we have to do in order to run our app? Well, what did I do when I ran it over here?
3:25
I went it down here and I said pip install -r requirements da-da-da, right? Same thing on a server. So we're going to go here after we do this.
3:33
We're going to run, well, let me put it down here and then I'll do another little example. So we're going to run that, and where's their requirements?
3:48
It's going to be /app/, so we have a movie service and that's just going to be right there. So requirements.txt.
3:58
That should be good, let's give it another try. Here go our requirements. It looks like it found the file.
4:09
Okay, super, that's all set up and it looks like we have our app running. I guess we could go and log in and just see if we can get it to work.
4:18
So let's go over here and say I'm going to do the -t. Remember before, we said that. We're going to do services like so. I'm going to build it.
4:29
I'm going to give it a name, knowing say docker run. For now we'll do -it. Services latest and bash.
4:39
Great, so what is the command we would like to run? We would like to run venv/bin/Python and we're going to run /app/app.py.
4:51
Now, this in some situations may work. It's not going to work now 'cause we need to change something really minor about how everything works.
5:01
Let's see what happens. Oh, it runs here but you'll see it won't run, oh, later. So it looks like everything's listening on our port.
5:10
And I'll show you one more tweak we got to make. You want to say docker run. So we could try to do this and see what we get.
5:22
And it's off and running. How 'about that? Okay, well, if it's happy, I'm happy. Let's see what we get if we go to this.
5:27
Well, can we go to that port? No. Because, of course, we haven't opened the port. So when I come over here, say -p 7007 goes to and from port 7007.
5:42
Let's try it one more time. It's running. Let's see what happens if we go to this URL. It was reset. Now, I want to show you this error.
5:56
I left this in on purpose. It's a little annoying but debugging these things is very challenging. So let's go back here to.
6:06
Well, it looks like it works. It says it's serving, right? Let's go back here and run this. And then we'll run our command that we ask it to run.
6:16
And I'll put an & on the back so that we can still interact with it. And we could do, hit local host on port 7000 and it's not working.
6:27
So here's the error that I was actually expecting us to get earlier. But notice it's not even listed. This is not a server 500.
6:33
This is no connection. What's going on? Let's look a little more carefully up here. When we look at the message, it's running on local host.
6:47
That maybe usually sounds like, oh, it just it's running here, it's fine. But that means it's only listening on the local loop back.
6:56
In order for us to get Responder to actually work we have to come over here and say an address equals, by the way, just pet peeve
7:08
of mine, what you type in there I have no idea. How do I know it's address? I had to go dig through the source code
7:15
several layers down to find out the keyword argument is address. It never has to be this way. You can always use default values
7:23
in keyword arguments, but they're explicit. Anyway, let me type address. It's going to be the string, either a full address or everything.
7:32
So now, notice our application has changed. Our Docker file has not changed. But we need to get a new Docker container
7:41
based on our new code. How do we do that? We're going to build like this. And you'll notice those files have changed.
7:50
And notice it copies those over and then it reruns the installer for the requirements. So one little trick that we can do is we know
8:01
that we're based on Responder. There may be other things that we're also based on but Responder is a pretty good bet.
8:08
You know, like, if you're doing Flask you can just say Flask. If you're doing Django, Django, whatever. So we can just say Responder right here
8:15
and then we can rerun the rest of the requirements 'cause most of the stuff that's slow comes from Responder. Why is this valuable?
8:22
This output, this calculation, this work, will be cached. So if we make little minor changes to our code we won't have to redo this every time.
8:35
So let's do that again. One more time, Docker build, just going to go through installing it one more time because we're now doing that new layer.
8:49
Of course that takes a while. But let's see what happens if we change our code again. So suppose I make a super important change
8:57
like that and we re-run our build. Watch this, done. Yep, everything's all finished. So this is a nice way to let your rebuild
9:06
happen much more quickly. It's your call whether or not you want to kind of hack it a little bit like that
9:10
but I like to do this. I think it's running now. Let's try this again. There we go. We're going to run it, we're going to expose that port.
9:20
It's running, and now notice, listening in on 0000. Now there's a server error, okay? That's progress. It doesn't sound like progress, but it is.
9:32
And what is the server error? It's that it can't find the template file that it's trying to work with 'cause its working directory is broken.
9:38
So we have one final change that we need to make over here. Let's go over here and we're going to I guess I'll do it after. Sure, we'll do it after.
9:49
We can say working dir is /app. So when our subsequent commands run either here or these ones here like this command right there
10:03
that's running, when that runs it'll be running from the perspective of that working directory. In fact, we could even write it like this if we want.
10:12
So let's do a Docker build one more time. Now we have our working directory applied. Let's try this one more time.
10:23
Server error, is it going to go away? Course it does, course it does because it's beautiful. So here we have our full Python app running right here.
10:32
If we go back we can get movies by IMDB number we can get the genres, and so on. So we have the movie service working
10:40
and if we were to re-run the container we would also have this working. Notice it's now going to talk to our local
10:48
notice MCL right here, little API calls. Okay, great, so it looks like we have our Python app running as well.