We will work today your Github repository. The repository with Python code, you have created last time:
|- .github/workflows
|- hello_world/
|- test/
|- main.py
|- Makefile
|- README.md
|- requirements.txt
\- test_requirements.txt
-
Check whether the application works locally following the steps from the project
README.md
.make test make lint make run
curl 127.0.0.1:5000/
-
Please verify your github flow works.
-
What is the dependency hell?
-
What are different approaches to address it?
- How does Python or NodeJS solve it?
- Linux distributions, e.g., deb or rpm? What is
snap
and what the difference is? - How did we address it on the cloud?
- What did Docker bring to the table?
-
Add to your project
Dockerfile
:FROM python:3 ARG APP_DIR=/usr/src/hello_world_printer WORKDIR /tmp ADD requirements.txt /tmp/requirements.txt RUN pip install -r /tmp/requirements.txt RUN mkdir -p $APP_DIR ADD hello_world/ $APP_DIR/hello_world/ ADD main.py $APP_DIR WORKDIR $APP_DIR CMD FLASK_APP=hello_world flask run --host=0.0.0.0
-
Let's see whether we can build the docker image for our app:
sudo docker build -t hello-world-printer .
# please verify whether you can see your image sudo docker images
Notice: if your application is simple, you can verify whether it starts during the building phase. Just change
CMD
toRUN
for testing -
If it works, please add a dedicated target in your
Makefile
:docker_build: docker build -t hello-world-printer .
and test it.
-
Docker provides us commands to run the application with one command:
sudo docker run \ --name hello-world-printer-dev \ -p 5000:5000 \ -d hello-world-printer
-
To check whether it runs properly:
# does it run? sudo docker ps # if you do not see your docker running: docker ps -a
# does it respond? curl 127.0.0.1:5000/
# what the logs say sudo docker logs hello-world-printer-dev
-
We might need to check the Docker from within:
sudo docker exec -it hello-world-printer-dev /bin/bash root@b7:/usr/src/hello_world_printer#
-
Time to add another target to our
Makefile
:docker_run: docker_build docker run \ --name hello-world-printer-dev \ -p 5000:5000 \ -d hello-world-printer
-
How to restart a Docker:
sudo docker stop hello-world-printer-dev sudo docker rm hello-world-printer-dev sudo make docker_run
-
The next step is to build your package (in our scenario a Docker Image) as a part of your CI/CD process (see docs). Please add at the end of your workflow file:
# ... - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Build and export to Docker uses: docker/build-push-action@v2 with: context: . load: true
-
We should also publish our Docker Image to a repository.
hub.docker.com
is the most popular one:- Create an account on hub.docker.com.
- Following the example from docs publish your image.
-
Run your Docker and mount the source code from your workstation to the Docker, so you can faster iterate. No need to rebuild your image, you can just restart the Docker:
sudo docker run \ --name hello-world-printer-dev \ -v $(pwd):/usr/src/hello_world_printer/ -p 5000:5000 \ -d hello-world-printer
-
Does my Dockerfile follow best practices? We have a linter for that:
docker run --rm -i hadolint/hadolint < Dockerfile # search & lint! find . -iname Dockerfile | xargs -I {} bash -c "echo {}; docker run --rm -i hadolint/hadolint < {}"
-
Security? Does the Docker image contain outdated packages? I recommend trivy.
trivy image hello-world-printer
-
Add XML output for your hello printer app.
-
Let the client, provide her or his name as a GET argument:
curl '127.0.0.1:5000?name=apolonia&output=json'
add relevant tests.
-
Generate JSON output with the built-in json library (do not forget about the tests):
import json
-
Generate XML output with lxml (do not forget about the tests):
pip3 install lxml
Hint: see this post on stackoverflow.
-
Execute the flask app with gunicorn.