From 1c80d924853cb4afc831b72dc9f4eb9a6ab13f0a Mon Sep 17 00:00:00 2001 From: David Andersson <51036209+jdkandersson@users.noreply.github.com> Date: Wed, 11 Sep 2024 06:24:39 +1000 Subject: [PATCH] docs: implement ux research for flask-framework tutorial (#690) * no longer collapse multipass * add installation instructions by operating system * fix message for when logs are available * shorten long commands * remove backgrounding app * add note explaining that the version change is not strictly required * include a note indicating the name influences the rock filename * clarify Docker intreraction * clarify Docker intreraction * add note about the size of the rock may vary * add explanation for how to stop following the logsd * change version to chiselled * include a note about when to use non-chiselled versions * add note about troubleshooting * fix spelling * remove back to back notes * remove two notes following each other * add macOS as a word * fix missing word --- docs/.wordlist.txt | 1 + docs/reuse/tutorial/setup.rst | 44 +++++++++++------- docs/tutorial/code/flask/task.yaml | 39 ++++++++++------ docs/tutorial/flask.rst | 72 +++++++++++++++++------------- 4 files changed, 94 insertions(+), 62 deletions(-) diff --git a/docs/.wordlist.txt b/docs/.wordlist.txt index 548774edd..21615ba82 100644 --- a/docs/.wordlist.txt +++ b/docs/.wordlist.txt @@ -68,6 +68,7 @@ lto LTS LXD lxd +macOS Multipass multipass nano diff --git a/docs/reuse/tutorial/setup.rst b/docs/reuse/tutorial/setup.rst index 8ec7c5c11..b37126d82 100644 --- a/docs/reuse/tutorial/setup.rst +++ b/docs/reuse/tutorial/setup.rst @@ -1,34 +1,46 @@ We recommend starting from a clean Ubuntu 22.04 installation. If you don't have one available, you can create one using `Multipass`_: -.. collapse:: How to create an Ubuntu 22.04 VM with Multipass +.. tabs:: - Is Multipass_ already installed and active? Check by running + .. tab:: Ubuntu - .. code-block:: bash + Is Multipass_ already installed and active? Check by running - sudo snap services multipass + .. code-block:: bash - If you see the ``multipass`` service but it isn't "active", then you'll - need to run ``sudo snap start multipass``. On the other hand, if you get - an error saying ``snap "multipass" not found``, then you must install - `Multipass `_: + snap services multipass - .. code-block:: bash + If you see the ``multipass`` service but it isn't "active", then you'll + need to run ``sudo snap start multipass``. On the other hand, if you get + an error saying ``snap "multipass" not found``, then you must install + `Multipass `_: - sudo snap install multipass + .. code-block:: bash - Then you can create the VM with the following command: + sudo snap install multipass - .. code-block:: text + .. tab:: Windows - multipass launch --disk 10G --name rock-dev 22.04 + See `Multipass installation instructions `_, switch + to Windows in the drop down. - Finally, once the VM is up, open a shell into it: + .. tab:: macOS - .. code-block:: bash + See `Multipass installation instructions `_, switch + to macOS in the drop down. - multipass shell rock-dev +Then you can create the VM with the following command: + +.. code-block:: text + + multipass launch --disk 10G --name rock-dev 22.04 + +Finally, once the VM is up, open a shell into it: + +.. code-block:: bash + + multipass shell rock-dev ---- diff --git a/docs/tutorial/code/flask/task.yaml b/docs/tutorial/code/flask/task.yaml index cf355d405..cfd93302e 100644 --- a/docs/tutorial/code/flask/task.yaml +++ b/docs/tutorial/code/flask/task.yaml @@ -17,18 +17,14 @@ execute: | pip install -r requirements.txt # [docs:create-venv-end] - # [docs:run-flask] flask run -p 8000 & - # [docs:run-flask-end] retry -n 5 --wait 2 curl localhost:8000 # [docs:curl-flask] curl localhost:8000 # [docs:curl-flask-end] - # [docs:stop-flask] kill $! - # [docs:stop-flask-end] # [docs:create-rockcraft-yaml] rockcraft init --profile flask-framework @@ -44,7 +40,9 @@ execute: | # [docs:ls-rock-end] # [docs:skopeo-copy] - sudo rockcraft.skopeo --insecure-policy copy oci-archive:flask-hello-world_0.1_amd64.rock docker-daemon:flask-hello-world:0.1 + sudo rockcraft.skopeo --insecure-policy \ + copy oci-archive:flask-hello-world_0.1_amd64.rock \ + docker-daemon:flask-hello-world:0.1 # [docs:skopeo-copy-end] # [docs:docker-images] @@ -52,7 +50,8 @@ execute: | # [docs:docker-images-end] # [docs:docker-run] - sudo docker run --rm -d -p 8000:8000 --name flask-hello-world flask-hello-world:0.1 + sudo docker run --rm -d -p 8000:8000 \ + --name flask-hello-world flask-hello-world:0.1 # [docs:docker-run-end] retry -n 5 --wait 2 curl localhost:8000 @@ -70,8 +69,11 @@ execute: | # [docs:stop-docker-end] # [docs:change-base] - sed -i "s/base: .*/base: bare\nbuild-base: ubuntu@22.04/g" rockcraft.yaml + sed -i \ + "s/base: .*/base: bare\nbuild-base: ubuntu@22.04/g" \ + rockcraft.yaml # [docs:change-base-end] + sed -i "s/version: .*/version: 0.1-chiselled/g" rockcraft.yaml # [docs:chisel-pack] rockcraft pack @@ -82,9 +84,12 @@ execute: | # [docs:ls-bare-rock-end] # [docs:docker-run-chisel] - sudo rockcraft.skopeo --insecure-policy copy oci-archive:flask-hello-world_0.1_amd64.rock docker-daemon:flask-hello-world:0.1 - sudo docker images flask-hello-world:0.1 - sudo docker run --rm -d -p 8000:8000 --name flask-hello-world flask-hello-world:0.1 + sudo rockcraft.skopeo --insecure-policy \ + copy oci-archive:flask-hello-world_0.1-chiselled_amd64.rock \ + docker-daemon:flask-hello-world:0.1-chiselled + sudo docker images flask-hello-world:0.1-chiselled + sudo docker run --rm -d -p 8000:8000 \ + --name flask-hello-world flask-hello-world:0.1-chiselled # [docs:docker-run-chisel-end] retry -n 5 --wait 2 curl localhost:8000 @@ -94,7 +99,7 @@ execute: | # [docs:stop-docker-chisel] sudo docker stop flask-hello-world - sudo docker rmi flask-hello-world:0.1 + sudo docker rmi flask-hello-world:0.1-chiselled # [docs:stop-docker-chisel-end] cat time-app.py > app.py @@ -103,9 +108,12 @@ execute: | # [docs:docker-run-update] rockcraft pack - sudo rockcraft.skopeo --insecure-policy copy oci-archive:flask-hello-world_0.2_amd64.rock docker-daemon:flask-hello-world:0.2 + sudo rockcraft.skopeo --insecure-policy \ + copy oci-archive:flask-hello-world_0.2_amd64.rock \ + docker-daemon:flask-hello-world:0.2 sudo docker images flask-hello-world:0.2 - sudo docker run --rm -d -p 8000:8000 --name flask-hello-world flask-hello-world:0.2 + sudo docker run --rm -d -p 8000:8000 \ + --name flask-hello-world flask-hello-world:0.2 # [docs:docker-run-update-end] retry -n 5 --wait 2 curl localhost:8000/time @@ -123,5 +131,8 @@ execute: | deactivate rm -rf .venv # delete all the files created during the tutorial - rm flask-hello-world_0.1_amd64.rock flask-hello-world_0.2_amd64.rock rockcraft.yaml app.py requirements.txt + rm flask-hello-world_0.1_amd64.rock \ + flask-hello-world_0.1-chiselled_amd64.rock \ + flask-hello-world_0.2_amd64.rock \ + rockcraft.yaml app.py requirements.txt # [docs:cleanup-end] diff --git a/docs/tutorial/flask.rst b/docs/tutorial/flask.rst index 8acf67ee6..01032b0fc 100644 --- a/docs/tutorial/flask.rst +++ b/docs/tutorial/flask.rst @@ -52,22 +52,11 @@ In the same directory, copy and save the following into a text file called .. literalinclude:: code/flask/app.py :language: python -Run the Flask application to verify that it works: - -.. literalinclude:: code/flask/task.yaml - :language: bash - :start-after: [docs:run-flask] - :end-before: [docs:run-flask-end] - :dedent: 2 - -.. note:: - The ``&`` at the end of the command runs the Flask application in the - background. You can continue to use your terminal as normal and will see all - the output from the Flask application in your terminal. To stop the Flask - application, you can use the ``kill`` command shown below. +Run the Flask application using ``flask run -p 8000`` to verify that it works. Test the Flask application by using ``curl`` to send a request to the root -endpoint: +endpoint. You may need a new terminal for this, if you are using Multipass use +``multipass shell rock-dev`` to get another terminal: .. literalinclude:: code/flask/task.yaml :language: bash @@ -77,13 +66,7 @@ endpoint: The Flask application should respond with ``Hello, world!``. -The Flask application looks good, so you can stop for now: - -.. literalinclude:: code/flask/task.yaml - :language: bash - :start-after: [docs:stop-flask] - :end-before: [docs:stop-flask-end] - :dedent: 2 +The Flask application looks good, so you can stop it for now using ``ctrl+C``. Pack the Flask application into a rock ====================================== @@ -99,14 +82,18 @@ creation and tailoring for a Flask application by using the :dedent: 2 The ``rockcraft.yaml`` file will automatically be created in your working -directory. Open it in a text editor and customise the ``name``, -``summary`` and ``description``. Ensure that ``platforms`` includes -the architecture of your host. For example, if your host uses the ARM +directory. Open it in a text editor and check that the ``name`` is +``flask-hello-world``. Ensure that ``platforms`` includes the architecture of +your host. For example, if your host uses the ARM architecture, include ``arm64`` in ``platforms``. .. note:: - For this tutorial, we'll use the ``name`` "flask-hello-world" and build - the rock on an ``amd64`` platform. + For this tutorial, we'll use the ``name`` ``flask-hello-world`` and assume + you are running on an ``amd64`` platform. Check the architecture of your + system using ``dpkg --print-architecture``. + + The ``name``, ``version`` and ``platform`` all influence the name of the + generated ``.rock`` file. Pack the rock: @@ -138,11 +125,13 @@ tutorial. on an ``amd64`` platform, the name of the ``.rock`` file will be different for you. + The size of the rock may vary for you. + Run the Flask rock with Docker ============================== You already have the rock as an `OCI `_ archive. Now you'll -need to import it into a format that Docker recognises: +need to load it into Docker: .. literalinclude:: code/flask/task.yaml :language: bash @@ -150,7 +139,7 @@ need to import it into a format that Docker recognises: :end-before: [docs:skopeo-copy-end] :dedent: 2 -Check that the image was successfully imported into Docker: +Check that the image was successfully loaded into Docker: .. literalinclude:: code/flask/task.yaml :language: bash @@ -216,12 +205,11 @@ You should expect to see something similar to this: 2024-06-21T03:41:45.078Z [flask] [2024-06-21 03:41:45 +0000] [18] [INFO] Booting worker with pid: 18 You can also choose to follow the logs by using the ``-f`` option with the -``pebble logs`` command above. +``pebble logs`` command above. To stop following the logs, press ``ctrl+c``. -.. important:: +.. note:: - To get the Flask application logs, the container must be running. This is - also valid for the remaining sections of this tutorial. + Applications logs are only available when the container is running. Cleanup ~~~~~~~ @@ -245,6 +233,11 @@ you can produce lean and production-ready rocks by getting rid of all the contents that are not needed for your Flask application to run. This results in a much smaller rock with a reduced attack surface. +.. note:: + It is recommended to run chiselled images in production. For development, + you may prefer non-chiselled images as they will include additional + development tooling (such as for debugging). + The first step towards chiselling your rock is to ensure you are using a ``bare`` :ref:`base `. In ``rockcraft.yaml``, change the ``base`` to ``bare`` and add @@ -261,6 +254,8 @@ In ``rockcraft.yaml``, change the ``base`` to ``bare`` and add the ``bare`` base. The command also adds a ``build-base`` which is required when using the ``bare`` base. +So that we can compare the size after chiselling, **open the** +``rockcraft.yaml`` file and change the ``version`` (e.g. to ``0.1-chiselled``). Pack the rock with the new ``bare`` :ref:`base `: .. literalinclude:: code/flask/task.yaml @@ -329,6 +324,12 @@ look like the following: Since you are creating a new version of your application, **open the** ``rockcraft.yaml`` file and change the ``version`` (e.g. to ``0.2``). +.. note:: + + ``rockcraft pack`` will create a new image with the updated code even if you + don't change the version. It is recommended to change the version whenever + you make changes to the application in the image. + Pack and run the rock using similar commands as before: .. literalinclude:: code/flask/task.yaml @@ -353,6 +354,11 @@ Finally, use ``curl`` to send a request to the ``/time`` endpoint: The updated application should respond with the current date and time (e.g. ``2024-06-21 09:47:56``). +.. note:: + + If you are getting a ``404`` for the ``/time`` endpoint, check the + :ref:`troubleshooting` steps below. + Cleanup ~~~~~~~ @@ -396,6 +402,8 @@ following: ---- +.. _troubleshooting: + Troubleshooting ===============