Portainer is a web ui on top of docker, making most of the commands available via a graphical user interface. It is available as a docker container, making it a nice first example of running a service as container.
-
Go to Docker Hub (https://hub.docker.com/), search for Portainer and go to the top result (with most pulls and stars)
-
Follow the 'Deploy Portainer' link and install portainer according the instructions under 'Quick start'.
Try to explain for yourself the options passed to the 'docker run' command.
Note that because portainer runs as a docker container it obviously doesn't have permission to access the docker deamon unless this is explicitly granted. This is done by mounting a socket from the host to the container as if it is a normal file.
-
Go to the portainer web interface (http://<your_ip>:9000), come up with a new password and choose to manage the Local Docker Enviroment
-
Take your time to look around. You should see that at least one container is running (portainer itself) and can inspect its properties
-
Remove the container via the web ui. This is equivalent to command 'docker rm -f <name of container, or container id>'.
-
Start a new container (arrow up in the terminal to select the previous command line). Log in again and notice that it rememberd the password. How is this possible?
-
Remove the container again. This time also remove the mounted volume on the host with
sudo rm -rf /opt/portainer/
Be careful with this command, don't type it wrong or we have to create a new VM for you!
-
Start a new container again and go to http://<your_ip>:9000. Now it should prompt you for a new password again
The task is to create an image for a simple python web service.
Tip: you can build the image and run it if the build is successful with a single command:
docker build -t greeting . && docker run --rm -p8000:8000 greeting
Use the arrow up to recall the command from history. You can do this at any time between the steps to see where you are.
-
cd into the greeting directory and create a Dockerfile there with the command
nano Dockerfile
-
We base the image on the popular lightweight Alpine image. Look it up on Docker Hub and see the example under 'Usage'. In this step you should:
- Add the FROM instruction
- Add the app folder to the image using ADD
- Set the entry point to
python service.py
using CMD (We will change it to Entrypoint later)
At this stage you should get an error like:
starting container process caused "exec: \"python\": executable file not found in $PATH"
-
Our app needs Python to be installed.
- Use
apk
to install the packagepython
(see the Alpine documentation on Docker hub for an example)
At this stage you should get an error like:
ImportError: No module named cherrypy
- Use
-
Our app needs the Python modules
cherrypy
andsimplejson
. Python modules can be installed using pip.- Use
apk
to install the packagepy-pip
- Run the command
pip install cherrypy simplejson
to install both Python modules
Now the service should start correctly. Go to http://:8000 to see if it is accessible. You should get the message:
jquery library is not loaded
- Use
-
Our page requires jquery-3.2.1.min.js in the
static
folder.- Use ADD to add
https://code.jquery.com/jquery-3.2.1.min.js
asstatic/jquery-3.2.1.min.js
This may be a good time to inspect the files in the container. The easiest way is to run the container with for example
ls -l
orls -l /static
as argument. Since we didn't specify an Entrypoint it will use/bin/sh
as entrypointReload the web page, this time it should work!
- Use ADD to add
-
Simulate some development effort by changing the greeting format in
app/service.conf
to something unique and rebuild and run again. You should now be greeted with your own unique message!
-
Replace the CMD by an ENTRYPOINT. This allows arguments to be passed to our service (but it doesn't allow easy access to the shell in the container anymore)
-
Expose port 8000 to make it visible for tools that that port is used, allowing auto-binding for example.
There is a docker registry installed on the local network of the VM's: cursusregistry:5000
-
Tag your greeting image with
cursusregistry:5000/<your-name>/greeting
. List your local images with:docker images
You should see that the image
greeting
andcursusregistry:5000/<your-name>/greeting
point to the same image IDNotice that because you didn't explicitly tag it with a version it was tagged with
latest
-
Push the image to the cursusregistry
The registry doesn't have a user interface, but you should be able to list the tags on your image with the following command:
curl -X GET http://cursusregistry:5000/v2/<your-name>/greeting/tags/list
This should print something like:
{"name":"<your-name>/greeting","tags":["latest"]}
-
Now tag your image again, but this time with the version tag
1.0
(i.e.cursusregistry:5000/<your-name>/greeting:1.0
), and push that to the registry too.Inspect the registry again if you like
-
Pull the image by one of its new tags and run it::
docker pull cursusregistry:5000/<your-name>/greeting
docker run --rm -p8000:8000 cursusregistry:5000/<your-name>/greeting
You should see that it pulls the image from the repository before starting it
Note: docker run would also pull the image, but only if it doesn't find the tag locally. Therefore we pull first.
-
Stop the image and this time run the image from your neighbour
-
Change the greeting format and build the image again like we did in the previous assignment Give it the tag
cursusregistry:5000/<your-name>/greeting:1.1
and push itYou now have a 1.0, 1.1 and latest in the repository, but to which image is latest pointing?
-
Fix this and pull and run the image by its
latest
tag