Hello to the second part of the “hello docker “ series, if your are new on docker please check the previous part by following this hello docker 😃 — Part I, In this lecture i will show you more advanced feature of the docker command line, also we will create a basic dockerized project for a simple python app with flask and we will push to dockerhub.
Common Docker commands
In this section I am going to show you the most used docker commands so let’s begin :
- To get info about your docker environment use :
docker info
- To remove a container use :
docker rm <name | ID>
- To remove an entire image use :
docker rmi <name | ID>
- To remove a container after run use :
docker run --rm <name|ID>
- To view current running containers use :
docker ps
- To view all running and exited containers use:
docker ps -a
- To view all and only the IDs of containers use :
docker ps -a -q
- To get all images use :
docker images
- To remove all images use :
docker rm $(docker ps -a -q)
- To view the images use :
docker images -f"dangling=true"
- To remove them use :
docker rmi $(docker images -f"dangling=true" -q)
- To run the container in background use :
docker run -d ... <name|ID>
That’s enough for now 😆, no lets build a simple python project with flask
The Flask app
Flask is a simple and powerful Framework for python like apache or tomcat... So let's begin :
The app.py
file
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello My Name is Hatem"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)
Make sure to install flask
with pip install flask
and run the script with python app.py
and open your browser on localhost:8080/
.
Let’s generate the requirements.txt
, we will not use pip freeze
here (we are not in a virtual environment) but we will use pipreqs
and make sure to install it with pip install pipreqs
.
use pipreqs <path to the python project>
to generate it.
Now let’s write the Dockerfile :
Dockerfile
FROM python:latest
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py .
CMD python app.py
FROM python:latest
: using python as a base image.WORKDIR /app
: using /app as a default directory.COPY requirements.txt .
compy this file to /appRUN pip install -r req..txt
: install the required dependenciesCOPY app.py .
: copy the app script to /appCMD python app.py
: The container entry point when we run it- Run the build process with
docker build -t hello_flask .
Run the container docker rn --rm -p 8080: 8080 hello_flask
, the -p 8080:8080
: will map the port 8080 on your host to the port 8080 in your container → this is the port mapping in docker, you can change the host port to any port you want and must be > 1024 ( ports < 1024 are reserved by the system).
Environment variables in Docker
An environment variable is a variable whose value is set outside the program, typically through the functionality built into the operating system or microservice. An environment variable is made up of a name/value pair, and any number may be created and available for reference at a point in time. → source for more information.
let’s use them in our example :
import os
@app.route("/")
def hello():
return "Hello My Name is {}".format(os.environ['NAME'])
the os.environ['NAME']
will fetch the NAME
variable and get its value and return it in the browser.
make sure to build the container again and run it like this :
docker run --rm -p 8080:8080 -e "NAME=steve" hello_flask
Volumes with Docker
In order to be able to save (persist) data and also to share data between containers, Docker came up with the concept of volumes. Quite simply, volumes are directories (or files) that are outside of the default Union File System and exist as normal directories and files on the host filesystem.
→ source
let’s make some change to our script :
@app.route("/name_from_file")
def name_from_file():
with open("files/name.txt","r") as file :
name= file.readline()
return "Hello My Name is {}".format(name)
Make sure to add a directory named “files” and add a file named “name.txt” that contains your name or whatever you want.
Now make the build again ! and run it with this command :
docker run --rm -v ${PWD}/files:/app/files -e "NAME=steve" -p 8080:8080 hello_flask
Now open your browser and type localhost:8080/name_from_file
, you should see the name that you already add it in the name.txt file. In this case, you can change the content of the file in real-time and reload the page, you should see the changes 😆.
Saving and publishing images
After finalizing your work there are two things you should do :
- Saving images to tarballs or compressed archives
- Publishing images to registries to be used in public or private…
Let's begin by saving our example image to a tarball by running this command docker save --output hello_flask.tar hello_flask
, now, check your current directory and type in the terminal ls -sh hello_flask.tar
to get the archive size. if you want to reduce the archive size use the gzip
command which is compression tools. Execute this command :
docker save hello_flask | gzip > hello_flask.tar.gz
and check the size again 😃. you can now upload them to your cloud storage or wherever you want. Now if you want to load the tar file to the docker engine simply run :
docker image load -i hello_flask.tar
Docker hub is our target now, to publish images in it you have to make an account first. the image name must be with this syntax account_name/image_name:image_tag
so let's rename our image by running this command :
docker tag hello_flask hatembt/hello_flask:latest
Now you have to log in to your account and push the image to the public :
docker login
docker push hatembt/hello_flask:latest
To pull the image just run docker pull hatembt/hello_flask:latest
, no need for credentials here 😃 .
Finally, I hope that this tutorial is helpful to everyone who wants to know docker. In Part III, we will go through a complex project ( Front-end + Back-end + Database) and we will use docker-compose as an orchestrator. If you have any feedback please share it with me Hatem Ben Tayeb 😆.