Dockerizing Python, Flask & Redis Application
- Prerequisite
- Install Docker on EC2 or VM, please refer this link
- Clone this repository
- Building and Pushing Docker Images
- Build flask application docker image using:
docker image build -t web1 .
- Inspect image
docker image inspect web1
- Tag image
docker image build -t web1:1.0 .
- Get list of docker images
docker image ls
- Remove the created image using:
docker image rm web1:1.0
- Login to docker hub using
docker login
- Prepare docker image to push to docker hub tagging repo name and version
docker image tag web1 dab8106/web1:latest
- Check the tagged image
docker image ls
- Push the image to docker hub
docker image push dab8106/web1
- Remove the docker image which you pushed to docker hub in last step
docker image rm -f [image id]
- Now pull the image from docker hub
docker pull dab8106/web1
- Build flask application docker image using:
- Running Docker Containers
- Tag image dab8106/web with web1
docker image tag dab8106/web1 web1
- Remove docker image with dab8106/web1
docker image rm dab8106/web1
- Run your docker image, check in browser by putting Public IP followed port 5000
docker container run -it -p 5000:5000 -e FLASK_APP=app.py web1 -e =execute command in Docker -p = Define container & host port -it = interactive mode
- Remove container manually using container ID
docker container rm [container id]
- Again run container
docker container run -it -p 5000:5000 -e FLASK_APP=app.py --rm --name web1 web1 -e =execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name
- Check for docker image
docker container ls -a
- Again run container
docker container run -it -p 5000:5000 -e FLASK_APP=app.py --rm --name web1 -d web1 -e =execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background
- Check container logs
docker container logs web1
- Check container logs in trailing mode
docker container logs -f web1
- Check container metrics
docker container stats
- Run a new container
docker container run -it -p 5000 -e FLASK_APP=app.py --rm --name web1_2 -d --restart on-failure web1 -e =execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background --restart on-failure = restarts the container when daemon or host fails and back online
- Stop the containers
docker container stop web1 docker container stop web1_2
- Tag image dab8106/web with web1
- Live Code Reloading With Volumes
- docker container run -it -p 5000:5000 -e FLASK_APP=app.py –rm –name web1 web1
- docker container run -it -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 –rm –name web1 web1
- Now change return value in app.py
To apply the changes you will need to rebuild the image
docker image build -t web1 . - We can’t be rebuild docker image very time whenever there’s a code change, so we will mount a directory to container
docker container run -it -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 --rm --name web1 -v $PWD:/app web1 -e =execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -v = Define volume
- Now make changes to return value in python, we wont need to build the image again rather our directory to container hence changes will be visible in browser
- Inspect container for attached volume
docker container inspect web1
- Linking Containers With Docker Networks
- Switch 04 Linking Containers With Docker Network directory of cloned repo & build a new docker image with tag as web2
docker image build -t web2 .
- Pull Redis based of alpine from docker hub
docker image pull redis:3.2-alpine
- List of docker network
docker network ls
- Inspect a network
docker network inspect bridge
- Run a redis container
docker run --rm -itd -p 6379:6379 --name redis redis:3.2-alpine -rm = removes container when it stopped -it = interactive mode -d = Run container is background --name = Define container name
- Run a flask container
docker container run --rm -itd -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 --name web2 -v $PWD:/app web2 -e =execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background -v = Define volume
- Check IP address of redis container
docker exec redis ifconfig
- Check IP address of web2 container
docker exec web2 ifconfig
- Ping redis conatiner from web2 using redis container’s IP address
docker exec web2 ping 172.17.0.3
- Check redis container hosts file
docker exec redis cat /etc/hosts
- Creating a custom bridge network
docker network create --driver bridge firstnetwork
- Inspect newly created network
docker network inspect firstnetwork
- Stop redis & web2 containers
docker container stop web2 docker container stop redis
- Run redis & web2 container in newly created network
docker container run --rm -itd -p 6379:6379 --name redis --net firstnetwork redis:3.2-alpine docker container run --rm -itd -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 --name web2 --net firstnetwork -v $PWD:/app web2 -e =execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background -v = Define volume -net = Define network
- Ping redis container from web2 using docker name, this is only possible in custom network not in default network
docker exec web2 ping redis
- Lets run some redis-cli commands to check counter in action
docker exec -it redis redis-cli KEYS * INCRBY web2_counter 1000000
- Stop web2 & redis containers
docker container stop web2 docker container stop redis
- Switch 04 Linking Containers With Docker Network directory of cloned repo & build a new docker image with tag as web2
- Persisting Data to Your Docker Host
- Create a new docker volume named as web2_redis
docker volume create web2_redis
- Get list of docker volumes
docker volume ls
- Inspect docker volumes
docker volume inspect web2_redis
- Run a redis container with new created docker volume attached to it
docker container run --rm -itd -p 6379:6379 --name redis --net firstnetwork -v web2_redis:/data redis:3.2-alpine -e = execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background -v = Define volume -net = Define network
- Launch Flask application in browser, so counter can be incremented
- Save state of redis using redis-cli, so counter state is saved
docker exec redis redis-cli SAVE
- Stop redis container
docker container stop redis
- Re-run redis container
docker container run --rm -itd -p 6379:6379 --name redis --net firstnetwork -v web2_redis:/data redis:3.2-alpine
- Launch Flask application in browser, so counter can be incremented
Here you will see counter is managed, this happens because state of redis container was saved inside a docker volume! - Stop web2 & redis container
docker container stop redis docker container stop web2
- Create a new docker volume named as web2_redis
- Sharing Data Between Containers
- Navigate to “06 Sharing Data Between Containers” directory of cloned repo, then build new docker image
In the docker file, we have expose a directory from container as a volume which can be used by other container a docker volumedocker build -t web2 .
- Run web2 container
docker container run --rm -itd -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 --name web2 --net firstnetwork -v $PWD:/app web2 -e = execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background -v = Define volume -net = Define network
- Run redis container
docker container run --rm -itd -p 6379:6379 --name redis --net firstnetwork --volumes-from web2 redis:3.2-alpine -e = execute command in Docker -p = Define container & host port -it = interactive mode -rm = removes container when it stopped --name = Define container name -d = Run container is background -v = Define volume -net = Define network --volumes-from = help you mount volume of other container
- You can login to redis container to verify if app/public/main.css is available or not
docker exec -it redis sh cd / ls -la cat app/public/main.css
- Stop both container
docker container stop web2 docker container stop redis
- Navigate to “06 Sharing Data Between Containers” directory of cloned repo, then build new docker image
- Optimizing Your Docker Images
- Navigate to “07 Optimizing Your Docker Images” & build an optimize image of this app
docker image build -t weboptimized .
- Navigate to “07 Optimizing Your Docker Images” & build an optimize image of this app
- Running Scripts When a Container Starts
- Navigate to “08 Running Scripts When a Container Starts” and run redis container
docker container run --rm -itd -p 6379:6379 --name redis --net firstnetwork redis:3.2-alpine
- Build a docker image tagged as webentrypoint, this docker file has statement for entrypoint
docker image build -t webentrypoint .
- Run your webentrypoint container
docker container run --rm -it -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 --name webentrypoint --net firstnetwork -v $PWD:/app webentrypoint CTRL + C
- Run your webentrypoint container
docker container run --rm -it -p 5000:5000 -e FLASK_APP=app.py -e FLASK_DEBUG=1 -e WEB2_COUNTER_MSG="Docker fans have visited this page" --name webentrypoint --net firstnetwork webentrypoint
- Navigate to “08 Running Scripts When a Container Starts” and run redis container
- Cleaning Up After Yourself
- Few clean up commands
docker system df docker system df -v docker system info docker system prune docker system prune -f docker system prune -a docker container stop web2 redis docker container stop $(docker container ls -a -q)
- Few clean up commands
- Adding Docker Compose Support
- Navigate to “09 Docker Compose”
- Rest is magic now! Done by do docker-compose.yml file
docker-compose up --build -d