- be able to dockerize a Flask web server
- come up with the steps that developers will use on a regular basis
Whenever you work with a dockerized application it's less obvious that, at some point in the past, someone put in place the groundwork on which you're executing your day-to-day work. Now there are some very critical parts in that groundwork that would make a normal workflow near impossible.
This exercise looks at that groundwork specifically for a Flask application.
End-goal: Write the Dockerfile for this Python application and come up with the workflow steps for an engineer to be able to pick it up and iterate on this application effectively.
-
- Navigate to the
./exercises/chapter3/python-basicdirectory in your command-line
- Navigate to the
Choice Time: Think about what base image we need. What are we looking for our environment to have, given the service we want to run on it?
-
- Find a Docker image on Docker Hub that is what you're looking for.
-
- Fill in the
FROMstep in theDockerfilewith that image name
- Fill in the
-
- Fill in the
COPYsteps in theDockerfile, with the files you need to run your application
- Fill in the
-
- Fill in the
RUNsteps that you need in theDockerfile
- Fill in the
Hint: If you're unsure what commands you need and are feeling a bit lost, why not try the approach mentioned in the previous chapter.
-
- Fill in the command that runs the application in the
CMDstep
- Fill in the command that runs the application in the
-
- Build your
Dockerfileinto animage
- Build your
-
- Run a new container using that image!
Debugging hint: This is where you start looking at docker help and what you can do with it.
Network hint: When running it, you need to expose Flask's port to a host port of your choosing.
-
- Make sure you can see the usage instructions on http://localhost:9000 in your browser and you're able to play with the API.
Hint: If not, is the container running? What are the container's logs showing? docker help is your friend again for these questions.
-
- With the build and run commands that you used, now fill in the
buildandrunplaceholder scripts that already exist
- With the build and run commands that you used, now fill in the
-
- Now, if someone is developing the Python code, what are the steps they would take to see their updates in the browser?
-
Which base Docker image did you use? What installation steps did you have to run before running your Python application? Could those steps have been avoided by using a different, more specific, base image?
-
Does your Docker container automagically reload the Python code when you change it? Why not?
Let's get some automagic-ness in our next steps!
-
- Turn on Flask reloading for when files change
-
- Change the configuration of your
docker runcall to make sure that as you change the Python files with your IDE, the changes get reflected in your running Python application automagically. Time for a docker volume!! 🎉
- Change the configuration of your
-
- Given file changes now get reflected inside the container, change the query text passed to the Giphy API to always append the word
scotlandto whatever the user is searching for. Test the effectiveness of your changes!
- Given file changes now get reflected inside the container, change the query text passed to the Giphy API to always append the word
-
- Provided you've tested the steps yourself, fill in the missing instructions in
scripts/helpso that new joiners will find their way around!
- Provided you've tested the steps yourself, fill in the missing instructions in
There's a dual achievement to what we've done here, even though we only intended for the developer workflow part of it.
For the developer workflow it's fairly obvious why this is beneficial, but regardless let's take a moment to list why this is better than just running the Python application without Docker:
- we did not install any system-wide or even user-wide dependencies on our host system, based on what our Python application requires.
I.e. imagine if we're installing geocoding OS libraries, PDF generation ones and so on, and we've have to manage those versions somehow, as well as make sure all these libraries exist on OS X + Ubuntu... eek!
- we've got complete control and isolation of our libraries, Python version and Pip dependencies.
I.e. there's no way installing another dependency on our host system is going to affect our application's dependencies by overwriting it, removing it, breaking it. And the manifest for managing these is all in one place, the Dockerfile.
The second achievement here and extremely important as well, is that we've suddenly created our package, as we called it in our initial introduction to Docker, which is the Docker image. The value out of that, we should not forget, is that it's cross-platform, distributable and deployable service, where the user is completely agnostic of what it's written in and what dependencies it may have. It is just an HTTP port to them.
-
What system dependencies does one need to install, besides the IDE, in order to work on this application?
-
Why doesn't
Ctrl+Cwork to stop the running container? Where should we look to fix this?