|
@@ -9,109 +9,137 @@ Python Web App
|
|
|
|
|
|
.. include:: example_header.inc
|
|
|
|
|
|
-The goal of this example is to show you how you can author your own
|
|
|
-Docker images using a parent image, making changes to it, and then
|
|
|
-saving the results as a new image. We will do that by making a simple
|
|
|
-hello Flask web application image.
|
|
|
+While using Dockerfiles is the preferred way to create maintainable
|
|
|
+and repeatable images, its useful to know how you can try things out
|
|
|
+and then commit your live changes to an image.
|
|
|
|
|
|
-**Steps:**
|
|
|
+The goal of this example is to show you how you can modify your own
|
|
|
+Docker images by making changes to a running
|
|
|
+container, and then saving the results as a new image. We will do
|
|
|
+that by making a simple 'hello world' Flask web application image.
|
|
|
|
|
|
-.. code-block:: bash
|
|
|
+Download the initial image
|
|
|
+--------------------------
|
|
|
+
|
|
|
+Download the ``shykes/pybuilder`` Docker image from the ``http://index.docker.io``
|
|
|
+registry.
|
|
|
|
|
|
- sudo docker pull shykes/pybuilder
|
|
|
+This image contains a ``buildapp`` script to download the web app and then ``pip install``
|
|
|
+any required modules, and a ``runapp`` script that finds the ``app.py`` and runs it.
|
|
|
|
|
|
-We are downloading the ``shykes/pybuilder`` Docker image
|
|
|
+.. _`shykes/pybuilder`: https://github.com/shykes/pybuilder
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
- URL=http://github.com/shykes/helloflask/archive/master.tar.gz
|
|
|
+ $ sudo docker pull shykes/pybuilder
|
|
|
|
|
|
-We set a ``URL`` variable that points to a tarball of a simple helloflask web app
|
|
|
+.. note:: This container was built with a very old version of docker
|
|
|
+ (May 2013 - see `shykes/pybuilder`_ ), when the ``Dockerfile`` format was different,
|
|
|
+ but the image can still be used now.
|
|
|
|
|
|
-.. code-block:: bash
|
|
|
+Interactively make some modifications
|
|
|
+-------------------------------------
|
|
|
|
|
|
- BUILD_JOB=$(sudo docker run -d -t shykes/pybuilder:latest /usr/local/bin/buildapp $URL)
|
|
|
+We then start a new container running interactively using the image.
|
|
|
+First, we set a ``URL`` variable that points to a tarball of a simple
|
|
|
+helloflask web app, and then we run a command contained in the image called
|
|
|
+``buildapp``, passing it the ``$URL`` variable. The container is
|
|
|
+given a name ``pybuilder_run`` which we will use in the next steps.
|
|
|
|
|
|
-Inside of the ``shykes/pybuilder`` image there is a command called
|
|
|
-``buildapp``, we are running that command and passing the ``$URL`` variable
|
|
|
-from step 2 to it, and running the whole thing inside of a new
|
|
|
-container. The ``BUILD_JOB`` environment variable will be set with the new container ID.
|
|
|
+While this example is simple, you could run any number of interactive commands,
|
|
|
+try things out, and then exit when you're done.
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
- sudo docker attach -sig-proxy=false $BUILD_JOB
|
|
|
+ $ sudo docker run -i -t -name pybuilder_run shykes/pybuilder bash
|
|
|
+
|
|
|
+ $$ URL=http://github.com/shykes/helloflask/archive/master.tar.gz
|
|
|
+ $$ /usr/local/bin/buildapp $URL
|
|
|
[...]
|
|
|
+ $$ exit
|
|
|
|
|
|
-While this container is running, we can attach to the new container to
|
|
|
-see what is going on. The flag ``--sig-proxy`` set as ``false`` allows you to connect and
|
|
|
-disconnect (Ctrl-C) to it without stopping the container.
|
|
|
+Commit the container to create a new image
|
|
|
+------------------------------------------
|
|
|
|
|
|
-.. code-block:: bash
|
|
|
+Save the changes we just made in the container to a new image called
|
|
|
+``/builds/github.com/shykes/helloflask/master``. You now have 3 different
|
|
|
+ways to refer to the container: name ``pybuilder_run``, short-id ``c8b2e8228f11``, or
|
|
|
+long-id ``c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9``.
|
|
|
|
|
|
- sudo docker ps -a
|
|
|
+.. code-block:: bash
|
|
|
|
|
|
-List all Docker containers. If this container has already finished
|
|
|
-running, it will still be listed here.
|
|
|
+ $ sudo docker commit pybuilder_run /builds/github.com/shykes/helloflask/master
|
|
|
+ c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9
|
|
|
|
|
|
-.. code-block:: bash
|
|
|
|
|
|
- BUILD_IMG=$(sudo docker commit $BUILD_JOB _/builds/github.com/shykes/helloflask/master)
|
|
|
+Run the new image to start the web worker
|
|
|
+-----------------------------------------
|
|
|
|
|
|
-Save the changes we just made in the container to a new image called
|
|
|
-``_/builds/github.com/hykes/helloflask/master`` and save the image ID in
|
|
|
-the ``BUILD_IMG`` variable name.
|
|
|
+Use the new image to create a new container with
|
|
|
+network port 5000 mapped to a local port
|
|
|
|
|
|
.. code-block:: bash
|
|
|
|
|
|
- WEB_WORKER=$(sudo docker run -d -p 5000 $BUILD_IMG /usr/local/bin/runapp)
|
|
|
+ $ sudo docker run -d -p 5000 --name web_worker /builds/github.com/shykes/helloflask/master /usr/local/bin/runapp
|
|
|
+
|
|
|
|
|
|
- **"docker run -d "** run a command in a new container. We pass "-d"
|
|
|
so it runs as a daemon.
|
|
|
- **"-p 5000"** the web app is going to listen on this port, so it
|
|
|
must be mapped from the container to the host system.
|
|
|
-- **"$BUILD_IMG"** is the image we want to run the command inside of.
|
|
|
- **/usr/local/bin/runapp** is the command which starts the web app.
|
|
|
|
|
|
-Use the new image we just created and create a new container with
|
|
|
-network port 5000, and return the container ID and store in the
|
|
|
-``WEB_WORKER`` variable.
|
|
|
|
|
|
-.. code-block:: bash
|
|
|
+View the container logs
|
|
|
+-----------------------
|
|
|
|
|
|
- sudo docker logs $WEB_WORKER
|
|
|
- * Running on http://0.0.0.0:5000/
|
|
|
-
|
|
|
-View the logs for the new container using the ``WEB_WORKER`` variable, and
|
|
|
+View the logs for the new ``web_worker`` container and
|
|
|
if everything worked as planned you should see the line ``Running on
|
|
|
http://0.0.0.0:5000/`` in the log output.
|
|
|
|
|
|
+To exit the view without stopping the container, hit Ctrl-C, or open another
|
|
|
+terminal and continue with the example while watching the result in the logs.
|
|
|
+
|
|
|
.. code-block:: bash
|
|
|
|
|
|
- WEB_PORT=$(sudo docker port $WEB_WORKER 5000 | awk -F: '{ print $2 }')
|
|
|
+ $ sudo docker logs -f web_worker
|
|
|
+ * Running on http://0.0.0.0:5000/
|
|
|
+
|
|
|
+
|
|
|
+See the webapp output
|
|
|
+---------------------
|
|
|
|
|
|
Look up the public-facing port which is NAT-ed. Find the private port
|
|
|
used by the container and store it inside of the ``WEB_PORT`` variable.
|
|
|
|
|
|
+Access the web app using the ``curl`` binary. If everything worked as planned you
|
|
|
+should see the line ``Hello world!`` inside of your console.
|
|
|
+
|
|
|
.. code-block:: bash
|
|
|
|
|
|
+ $ WEB_PORT=$(sudo docker port web_worker 5000 | awk -F: '{ print $2 }')
|
|
|
+
|
|
|
# install curl if necessary, then ...
|
|
|
- curl http://127.0.0.1:$WEB_PORT
|
|
|
- Hello world!
|
|
|
+ $ curl http://127.0.0.1:$WEB_PORT
|
|
|
+ Hello world!
|
|
|
|
|
|
-Access the web app using the ``curl`` binary. If everything worked as planned you
|
|
|
-should see the line ``Hello world!`` inside of your console.
|
|
|
|
|
|
-**Video:**
|
|
|
+Clean up example containers and images
|
|
|
+--------------------------------------
|
|
|
+
|
|
|
+.. code-block:: bash
|
|
|
|
|
|
-See the example in action
|
|
|
+ $ sudo docker ps --all
|
|
|
+
|
|
|
+List ``--all`` the Docker containers. If this container had already finished
|
|
|
+running, it will still be listed here with a status of 'Exit 0'.
|
|
|
+
|
|
|
+.. code-block:: bash
|
|
|
|
|
|
-.. raw:: html
|
|
|
+ $ sudo docker stop web_worker
|
|
|
+ $ sudo docker rm web_worker pybuilder_run
|
|
|
+ $ sudo docker rmi /builds/github.com/shykes/helloflask/master shykes/pybuilder:latest
|
|
|
|
|
|
- <iframe width="720" height="400" frameborder="0"
|
|
|
- sandbox="allow-same-origin allow-scripts"
|
|
|
- srcdoc="<body><script type="text/javascript"
|
|
|
- src="https://asciinema.org/a/2573.js"
|
|
|
- id="asciicast-2573" async></script></body>">
|
|
|
- </iframe>
|
|
|
+And now stop the running web worker, and delete the containers, so that we can
|
|
|
+then delete the images that we used.
|
|
|
|
|
|
-Continue to :ref:`running_ssh_service`.
|