Hello Docker 😃 — Part II

Hello Docker 😃 — Part II

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 /app RUN pip install -r req..txt : install the required dependencies
  • COPY app.py . : copy the app script to /app
  • CMD 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 😆.

Thank you 😃