In this article, I'll try to show you how to develop Python applications (primarily Web applications) with Docker. While I am personally focused on Python's flask micro-framework, the purpose of this article is to demonstrate how to better develop and share applications (applications developed by any language and framework) through Docker. By encapsulating dependencies, Docker greatly reduces the gap between the development environment and the formal product.
Most Python developers use virtualenv in development. It provides an easy-to-use mechanism for applications to use their own proprietary dependencies, which may conflict with other applications or operating systems (especially in different Pyhton versions, as well as different versions of libraries, and so on). Personally, I have not been much interested in virtualenv for the following reasons:
I often forget to turn it on, or forget to switch it when I switch projects, and it's confusing to have ambiguous error messages.
It does not provide "pure" isolation, only Python-level isolation (System libraries and non-Python dependencies can still be problematic).
I don't usually want to run it in a formal product, which means inconsistencies between the development environment and the formal product.
It feels a bit of a "hacker" approach: it relies on modifying the script and setting up a new path to implement it.
(see Pythonrants's article for more information on why you might not want to use virtualenv)
So, how to do Docker to become better? Docker essentially provides a very lightweight VMS (described as "containers") that we can use to create a high standard of isolation and greatly reduce mismatch in development and product environments. (If you're not familiar with Docker and want to learn more, you can check out my talk about Docker at the Edinburgh Technical Symposium).
When we build a small visualization web APP, I and Mark Coleman Use this method (the documentation is here). This (inside) outlines a basic image to install Python 2.7, as well as some flask management and PostgreSQL content. I will develop a Hello World Web application based on this image. I assume that you are developing on Linux and that you already have git, and that the instructions for installing Docker,macos should be very similar. Start by cloning and establishing a basic mirror image:
$ git clone https://github.com/mrmrcoleman/python_webapp
$ docker build–t python _ WebApp.
Now, we need to add some code to the container and specify it in detail. We're going to create a new project that only points to Docker mirroring to do this, rather than directly modifying the previous project.
Create a new project with the following structure:
├──dockerfile
├──example _ app
│├──app
││ ├──__init__. py
││ └──views. py
│└──__i nit__. Py
├──example_app. Wsgi
or clone a sample project for this address: https://github.com/amouat/example_app.git
Write in example_app/app/_init_.py:
From flask import flask
app = Flask (__name__) from
app import views
Make another _init_.py empty. Write in views.py:
From app Import app
@ App. Route ('/')
@ App. Route ('/index ')
def index (): Return
"Hello, world!"
These are the smallest flask versions of our Hello World application. I've also used similar code in this tutorial, so if you've just contacted flask or python, you can use Docker instead of virtualenv to continue learning based on the tutorials mentioned above.
In order for it to run inside the Docker container, we also need to do some operations. In our instance Apache server, the Example_app.wsgi file contains instructions to connect to the Python code and the Web server. The file should contain the following contents:
Import Site
site. Addsitedir ('/opt/example_app/') from
app import app as application
Ultimately, we need a dockerfile to build the container and run the container. In our case, it looks like this:
From Python_webapp
maintainer amouat
ADD example_app. Wsgi/var/www/flaskapp/flaskapp. Wsgi
CMD SE Rvice apache2 start && tail–f/var/log/apache2/error. Log
Add that behavior starts WSGI injected some code. CMD line when you start the container, start the Apache Web server and get any possible error messages and send them to stdout.
If you are doing the following:
Copy Code code as follows:
$ Docker Build–t Example _ app.
$ docker run–p 5000:5000–v $ (PWD)/Example_app:/Opt/example_app/–i–t-Example_app
You should get the feedback: Open the address localhost:5000 through the browser and you'll see that your site is running. If you are actually running in a VM or vagrant, remember to open port 5000.
Now that we're running the Web server, it's very close to what we're using in the product (I intentionally use Apache to do this rather than the Python Default Web server). We inject code into the container by mapping from the host to the container, or add code to the Dockerfile command line with Add, but in that case, the container needs to be rebuilt each time the team code changes.
However, this is still not very good; in development we really want to use the Python Web server that helps us debug a lot. The pleasure is that we do not have to make any changes to the dockerfile. At the beginning of the Example_app file from creating a run.py file, follow the contents:
! Flask/bin/python
from app Import app
. Run (debug = True, host = ' 0.0.0.0 ')
This will start the Python Web server with debugging and listen for all connections, and we can access them from outside the container. Now reboot the container with the following command:
$ docker run -p 5000:5000 -v $(pwd)/example_app:/opt/example_app/ -i -t example_app python /opt/example_app/run.py
You can see the Web page running again. This time we explicitly provide the command to run ("python/opt/example_app/ryn.py"), which overrides the setup of the CMD line in Dockerfile. Now if you edit the source program on the host, you can immediately see the changes on the page.
Let's take a moment to see what we've learned:
A Web application running in an isolation container that encapsulates the application's Python dependencies and system dependencies completely.
Ability to use an existing editor or IDE to develop code and view changes directly, just as you would for local editing.
Closer to the operating environment of the formal product than before.
No use of virtualenv.
If you want to know how to build a program in this way, take a look at Mark Coleman's article on the aforementioned Visual Web application.
Unfortunately, it's not perfect. There are also a few questions to follow:
You may still encounter situations where you need to use VIRTUALENV or its equivalent solution, such as the conflict between the operating system version of the library and the version you need for your program.
We haven't fully solved the data-hosting problem yet, and we still need to do some testing.
I assume that the "product" is a docker container, but this is often not the case and Docker hosting itself is just getting started.
Still, I think this is a big step towards a better future for software development, which greatly eases the pain of deploying software and managing dependencies.