It can be confusing to figure out how to use Docker containers in your Python and Bottle development environment workflow. This tutorial will quickly show you the exact steps to get Docker up and running on macOS with a working Bottle web application
This tutorial is written for Python 3. It may work with Python 2 but it has not been testing with that soon-to-be deprecated 2.7 version. You should really be using Python 3, preferrably the latest release which is currently 3.6.5.
Docker for Mac is necessary to run Docker containers. I recommend that you use the stable release unless you have an explicit purpose for the edge channel.
Within the Docker container we will use:
All for the Dockerfile and the Bottle project are available open source under the MIT license on GitHub under the docker-bottle-mac directory of the blog-code-examples repository.
We must install Docker before we can spin up our containers. Jump to the next section if you already have Docker for Mac installed and working on your computer.
On your Mac, download the Docker Community Edition (CE) for Mac installer.
Open Finder and go to the downloads folder where the installation file is located. Follow the installation steps and open Terminal when the installer finishes.
Test your Docker installation by running the docker
command along with the
--version
flag:
docker --version
If Docker is installed correctly you should see the following output:
Docker version 18.03.1-ce, build 9ee9f40
Note that Docker runs through a system agent you can find in the menu bar.
Docker is now installed so we can run a container and write a simple Bottle application to test running an app within the container.
Docker needs to know what we want in our container so we specify an
image using a Dockerfile
.
# this is an official Python runtime, used as the parent image
FROM python:3.6.5-slim
# set the working directory in the container to /app
WORKDIR /app
# add the current directory to the container as /app
ADD . /app
# execute everyone's favorite pip command, pip install -r
RUN pip install --trusted-host pypi.python.org -r requirements.txt
# unblock port 80 for the Bottle app to run on
EXPOSE 80
# execute the Flask app
CMD ["python", "app.py"]
Save the Dockerfile and then on the commandline run:
docker build -t bottledock .
The above docker build
file uses the -t
flag to tag the image with
the name of bottledock
.
If the build worked successfully the shell will show some completed output like the following:
$ docker build -t bottledock .
Sending build context to Docker daemon 16.38kB
Step 1/6 : FROM python:3.6.5-slim
3.6.5-slim: Pulling from library/python
f2aa67a397c4: Pull complete
19cc085bc22b: Pull complete
83bd7790bc68: Pull complete
8b3329adba1b: Pull complete
d0a8fd6eb5d0: Pull complete
Digest: sha256:56100f5b5e299f4488f51ea81cc1a67b5ff13ee2f926280eaf8e527a881afa61
Status: Downloaded newer image for python:3.6.5-slim
---> 29ea9c0b39c6
Step 2/6 : WORKDIR /app
Removing intermediate container 627538eb0d39
---> 26360255c163
Step 3/6 : ADD . /app
---> 9658b91b29db
Step 4/6 : RUN pip install --trusted-host pypi.python.org -r requirements.txt
---> Running in f0d0969f3066
Collecting bottle==0.12.13 (from -r requirements.txt (line 1))
Downloading https://files.pythonhosted.org/packages/bd/99/04dc59ced52a8261ee0f965a8968717a255ea84a36013e527944dbf3468c/bottle-0.12.13.tar.gz (70kB)
Building wheels for collected packages: bottle
Running setup.py bdist_wheel for bottle: started
Running setup.py bdist_wheel for bottle: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/76/a0/b4/2a3ee1a32d0506931e558530258de1cc04b628eff1b2f008e0
Successfully built bottle
Installing collected packages: bottle
Successfully installed bottle-0.12.13
Removing intermediate container f0d0969f3066
---> 0534575c8067
Step 5/6 : EXPOSE 80
---> Running in 14e49938d3be
Removing intermediate container 14e49938d3be
---> 05e087d2471d
Step 6/6 : CMD ["python", "app.py"]
---> Running in ca9738bfd06a
Removing intermediate container ca9738bfd06a
---> 9afb4f01e0d3
Successfully built 9afb4f01e0d3
Successfully tagged bottledock:latest
We can also see the image with the docker image ls
command. Give that
a try now:
docker image ls
Our tag name should appear in the images list:
REPOSITORY TAG IMAGE ID CREATED SIZE
bottledock latest 9afb4f01e0d3 About a minute ago 145MB
Our image is ready to load as a container so we can code a short Bottle web app for testing and then further development.
It is time to code a simple "Hello, World!"-style Bottle app to test
running Python code within our Docker container. Within the current
project directory, create a file named app.py
with the following contents:
import bottle
from bottle import route, run
app = bottle.default_app()
@route('/')
def hello_world():
return "Hello, world! (From Full Stack Python)"
if __name__ == "__main__":
run(host="0.0.0.0", port=8080, debug=True, reloader=True)
The above code returns a simple "Hello, world!" message when executed by the Bottle development server and contacted by a client.
We need just one more file to specify our bottle
dependency. Create
a requirements.txt
file within the same directory as app.py
:
bottle==0.12.13
Make sure both the app.py
and requirements.txt
file are saved then
we can give the code a try.
Now that we have our image in hand along with the Python code in a file
we can run the image as a container with the docker run
command. Execute
the following command, making sure to replace the absolute path for the
volume to your own directory.
docker run -p 5000:8080 --volume=/Users/matt/devel/py/blog-code-examples/docker-bottle-macapp bottledock
If you receive the error
python: can't open file 'app.py': [Errno 2] No such file or directory
then
you likely did not change /Users/matt/devel/py/bottledocker
to the
directory where your project files, especially app.py
, are located.
Everything worked when you see a simple text-based HTTP response like what is shown above in the screenshot of my Chrome browser.
We just installed Docker and wrote a Bottle web app to run inside a container. That is just the beginning of how you can integrate Docker into your workflow.
Next up take a look at the Bottle, Docker and deployment pages for more tutorials.
Questions? Let me know via a GitHub issue ticket on the Full Stack Python repository, on Twitter @fullstackpython or @mattmakai.
Do you see a typo, syntax issue or just something that's confusing in this blog post? Fork this page's source on GitHub and submit a pull request with a fix or file an issue ticket on GitHub.