From 3036b5a196fdbb744f94299c82dc44078361bdae Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 14 Feb 2014 21:02:54 +1000 Subject: [PATCH 1/4] rejig the helloflask example as more advanced, and move it to the end Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) --- docs/sources/examples/index.rst | 2 +- docs/sources/examples/python_web_app.rst | 113 ++++++++++++----------- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/docs/sources/examples/index.rst b/docs/sources/examples/index.rst index cd08107e7a..cf9ed9340a 100644 --- a/docs/sources/examples/index.rst +++ b/docs/sources/examples/index.rst @@ -16,7 +16,6 @@ to more substantial services like those which you might find in production. :maxdepth: 1 hello_world - python_web_app nodejs_web_app running_redis_service running_ssh_service @@ -26,3 +25,4 @@ to more substantial services like those which you might find in production. running_riak_service using_supervisord cfengine_process_management + python_web_app diff --git a/docs/sources/examples/python_web_app.rst b/docs/sources/examples/python_web_app.rst index f31b31b7d2..b44c0e1ee5 100644 --- a/docs/sources/examples/python_web_app.rst +++ b/docs/sources/examples/python_web_app.rst @@ -9,85 +9,86 @@ 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 prefered 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. + +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. **Steps:** .. code-block:: bash - sudo docker pull shykes/pybuilder + $ sudo docker pull shykes/pybuilder + +Download the ``shykes/pybuilder`` Docker image from the ``http://index.docker.io`` +registry. Note that this container was built with a very old version of docker +(May 2013), but can still be used now. -We are downloading the ``shykes/pybuilder`` Docker image .. code-block:: bash - URL=http://github.com/shykes/helloflask/archive/master.tar.gz + $ sudo docker run -i -t -name pybuilder_run shykes/pybuilder bash -We set a ``URL`` variable that points to a tarball of a simple helloflask web app + $$ URL=http://github.com/shykes/helloflask/archive/master.tar.gz + $$ /usr/local/bin/buildapp $URL + [lots of output later] + $$ exit + + +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. + +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 - BUILD_JOB=$(sudo docker run -d -t shykes/pybuilder:latest /usr/local/bin/buildapp $URL) - -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. - -.. code-block:: bash - - sudo docker attach -sig-proxy=false $BUILD_JOB - [...] - -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. - -.. code-block:: bash - - sudo docker ps -a - -List all Docker containers. If this container has already finished -running, it will still be listed here. - -.. code-block:: bash - - BUILD_IMG=$(sudo docker commit $BUILD_JOB _/builds/github.com/shykes/helloflask/master) + $ sudo docker commit pybuilder_run /builds/github.com/shykes/helloflask/master + c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9 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. +``/builds/github.com/hykes/helloflask/master``. You now have 3 different +ways to refer to the container, name, short-id ``c8b2e8228f11``, or +long-id ``c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9``. .. code-block:: bash - WEB_WORKER=$(sudo docker run -d -p 5000 $BUILD_IMG /usr/local/bin/runapp) + $ WEB_WORKER=$(sudo docker run -d -p 5000 /builds/github.com/hykes/helloflask/master /usr/local/bin/runapp) + +Use the new image to create a new container with +network port 5000, and return the container ID and store in the +``WEB_WORKER`` variable (rather than naming a container/image, you can use the ID's). - **"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 - sudo docker logs $WEB_WORKER + $ sudo docker logs -f $WEB_WORKER * Running on http://0.0.0.0:5000/ View the logs for the new container using the ``WEB_WORKER`` variable, 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 }') + $ WEB_PORT=$(sudo docker port $WEB_WORKER 5000 | awk -F: '{ print $2 }') 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. @@ -95,23 +96,25 @@ used by the container and store it inside of the ``WEB_PORT`` variable. .. code-block:: bash # 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:** +.. code-block:: bash -See the example in action + $ sudo docker ps --all -.. raw:: html +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 + + $ sudo docker stop $WEB_WORKER + $ sudo docker rm $WEB_WORKER pybuilder_run + $ sudo docker rmi /builds/github.com/shykes/helloflask/master shykes/pybuilder:latest + +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`. From f535a58959809dbb613bf529019f26cc6ae0c6f9 Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 14 Feb 2014 21:27:57 +1000 Subject: [PATCH 2/4] swap busybox for ubuntu, its quicker.. Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) --- docs/sources/examples/hello_world.rst | 30 +++++++++++++-------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/docs/sources/examples/hello_world.rst b/docs/sources/examples/hello_world.rst index fd5d6421c3..c8ecb0f6c2 100644 --- a/docs/sources/examples/hello_world.rst +++ b/docs/sources/examples/hello_world.rst @@ -4,9 +4,6 @@ .. _examples: -Hello World ------------ - .. _running_examples: Check your Docker install @@ -18,7 +15,7 @@ your Docker install, run the following command: .. code-block:: bash # Check that you have a working install - docker info + $ sudo docker info If you get ``docker: command not found`` or something like ``/var/lib/docker/repositories: permission denied`` you may have an incomplete @@ -30,27 +27,28 @@ Please refer to :ref:`installation_list` for installation instructions. .. _hello_world: Hello World -=========== +----------- .. include:: example_header.inc This is the most basic example available for using Docker. -Download the base image which is named ``ubuntu``: +Download the small base image named ``busybox``: .. code-block:: bash - # Download an ubuntu image - sudo docker pull ubuntu + # Download an busybox image + $ sudo docker pull busybox -Alternatively to the ``ubuntu`` image, you can select ``busybox``, a bare -minimal Linux system. The images are retrieved from the Docker -repository. +The ``busybox`` image is a minimal Linux system. You can do the same +with any number of other images, such as ``debian``, ``ubuntu`` or ``centos``. +The images can be found and retrieved using the `Docker index`_. +.. _Docker index: http://index.docker.io .. code-block:: bash - sudo docker run ubuntu /bin/echo hello world + $ sudo docker run busybox /bin/echo hello world This command will run a simple ``echo`` command, that will echo ``hello world`` back to the console over standard out. @@ -58,7 +56,7 @@ This command will run a simple ``echo`` command, that will echo ``hello world`` - **"sudo"** execute the following commands as user *root* - **"docker run"** run a command in a new container -- **"ubuntu"** is the image we want to run the command inside of. +- **"busybox"** is the image we are running the command in. - **"/bin/echo"** is the command we want to run in the container - **"hello world"** is the input for the echo command @@ -82,7 +80,7 @@ See the example in action .. _hello_world_daemon: Hello World Daemon -================== +------------------ .. include:: example_header.inc @@ -172,14 +170,14 @@ See the example in action id="asciicast-2562" async>"> -The next example in the series is a :ref:`python_web_app` example, or +The next example in the series is a :ref:`nodejs_web_app` example, or you could skip to any of the other examples: -* :ref:`python_web_app` * :ref:`nodejs_web_app` * :ref:`running_redis_service` * :ref:`running_ssh_service` * :ref:`running_couchdb_service` * :ref:`postgresql_service` * :ref:`mongodb_image` +* :ref:`python_web_app` From b05602a0fe6d9b9731cee0008fbac27250f361bd Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Fri, 14 Feb 2014 22:41:59 +1000 Subject: [PATCH 3/4] update a new movie: http://asciinema.org/a/7658 Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) --- docs/sources/examples/hello_world.rst | 8 +-- docs/sources/examples/python_web_app.rst | 80 ++++++++++++++++-------- 2 files changed, 56 insertions(+), 32 deletions(-) diff --git a/docs/sources/examples/hello_world.rst b/docs/sources/examples/hello_world.rst index c8ecb0f6c2..63362e7d7b 100644 --- a/docs/sources/examples/hello_world.rst +++ b/docs/sources/examples/hello_world.rst @@ -2,8 +2,6 @@ :description: A simple hello world example with Docker :keywords: docker, example, hello world -.. _examples: - .. _running_examples: Check your Docker install @@ -37,7 +35,7 @@ Download the small base image named ``busybox``: .. code-block:: bash - # Download an busybox image + # Download a busybox image $ sudo docker pull busybox The ``busybox`` image is a minimal Linux system. You can do the same @@ -71,8 +69,8 @@ See the example in action ---- diff --git a/docs/sources/examples/python_web_app.rst b/docs/sources/examples/python_web_app.rst index b44c0e1ee5..6992d0f7f8 100644 --- a/docs/sources/examples/python_web_app.rst +++ b/docs/sources/examples/python_web_app.rst @@ -9,7 +9,7 @@ Python Web App .. include:: example_header.inc -While using Dockerfiles is the prefered way to create maintainable +While using Dockerfiles is the preffered 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. @@ -18,29 +18,29 @@ 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. -**Steps:** +Download the initial image +-------------------------- + +Download the ``shykes/pybuilder`` Docker image from the ``http://index.docker.io`` +registry. + +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. + +.. _`shykes/pybuilder`: https://github.com/shykes/pybuilder .. code-block:: bash $ sudo docker pull shykes/pybuilder -Download the ``shykes/pybuilder`` Docker image from the ``http://index.docker.io`` -registry. Note that this container was built with a very old version of docker -(May 2013), but can still be used now. +.. 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. +Interactively make some modifications +------------------------------------- -.. code-block:: bash - - $ 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 - [lots of output later] - $$ exit - - -We then start a new container running interactively using the -image. +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 @@ -51,8 +51,15 @@ try things out, and then exit when you're done. .. code-block:: bash - $ sudo docker commit pybuilder_run /builds/github.com/shykes/helloflask/master - c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9 + $ 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 + +Commit the container to create a new image +------------------------------------------ Save the changes we just made in the container to a new image called ``/builds/github.com/hykes/helloflask/master``. You now have 3 different @@ -61,12 +68,22 @@ long-id ``c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9``. .. code-block:: bash - $ WEB_WORKER=$(sudo docker run -d -p 5000 /builds/github.com/hykes/helloflask/master /usr/local/bin/runapp) + $ sudo docker commit pybuilder_run /builds/github.com/shykes/helloflask/master + c8b2e8228f11b8b3e492cbf9a49923ae66496230056d61e07880dc74c5f495f9 + + +Run the new image to start the web worker +----------------------------------------- Use the new image to create a new container with network port 5000, and return the container ID and store in the ``WEB_WORKER`` variable (rather than naming a container/image, you can use the ID's). +.. code-block:: bash + + $ WEB_WORKER=$(sudo docker run -d -p 5000 /builds/github.com/hykes/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 @@ -74,10 +91,8 @@ network port 5000, and return the container ID and store in the - **/usr/local/bin/runapp** is the command which starts the web app. -.. code-block:: bash - - $ sudo docker logs -f $WEB_WORKER - * Running on http://0.0.0.0:5000/ +View the container logs +----------------------- View the logs for the new container using the ``WEB_WORKER`` variable, and if everything worked as planned you should see the line ``Running on @@ -88,19 +103,30 @@ 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! -Access the web app using the ``curl`` binary. If everything worked as planned you -should see the line ``Hello world!`` inside of your console. + +Clean up example containers and images +-------------------------------------- .. code-block:: bash From 29f7e1bfcbe6654d962a55eb5006e248284b9e0c Mon Sep 17 00:00:00 2001 From: Sven Dowideit Date: Tue, 18 Feb 2014 13:23:18 +1000 Subject: [PATCH 4/4] suggested improvements Docker-DCO-1.1-Signed-off-by: Sven Dowideit (github: SvenDowideit) --- docs/sources/examples/python_web_app.rst | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/sources/examples/python_web_app.rst b/docs/sources/examples/python_web_app.rst index 6992d0f7f8..5b8e3f6b4b 100644 --- a/docs/sources/examples/python_web_app.rst +++ b/docs/sources/examples/python_web_app.rst @@ -9,7 +9,7 @@ Python Web App .. include:: example_header.inc -While using Dockerfiles is the preffered way to create maintainable +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. @@ -62,8 +62,8 @@ Commit the container to create a new image ------------------------------------------ Save the changes we just made in the container to a new image called -``/builds/github.com/hykes/helloflask/master``. You now have 3 different -ways to refer to the container, name, short-id ``c8b2e8228f11``, or +``/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``. .. code-block:: bash @@ -76,12 +76,11 @@ Run the new image to start the web worker ----------------------------------------- Use the new image to create a new container with -network port 5000, and return the container ID and store in the -``WEB_WORKER`` variable (rather than naming a container/image, you can use the ID's). +network port 5000 mapped to a local port .. code-block:: bash - $ WEB_WORKER=$(sudo docker run -d -p 5000 /builds/github.com/hykes/helloflask/master /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" @@ -94,7 +93,7 @@ network port 5000, and return the container ID and store in the View the container logs ----------------------- -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. @@ -103,7 +102,7 @@ terminal and continue with the example while watching the result in the logs. .. code-block:: bash - $ sudo docker logs -f $WEB_WORKER + $ sudo docker logs -f web_worker * Running on http://0.0.0.0:5000/ @@ -118,7 +117,7 @@ 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 }') + $ 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 @@ -137,8 +136,8 @@ running, it will still be listed here with a status of 'Exit 0'. .. code-block:: bash - $ sudo docker stop $WEB_WORKER - $ sudo docker rm $WEB_WORKER pybuilder_run + $ sudo docker stop web_worker + $ sudo docker rm web_worker pybuilder_run $ sudo docker rmi /builds/github.com/shykes/helloflask/master shykes/pybuilder:latest And now stop the running web worker, and delete the containers, so that we can