Doker-compose Running Flask Application Best Practices

Posted by martins on Tue, 14 May 2019 11:55:21 +0200

background

Before deploying applications, various environment configurations were needed, and various shell operations were needed to build a set of available services. Now with Docker, deployment is easier, configuration errors are less likely, and environment inconsistencies are less likely. It solves the problems of running in the local environment and migrating to the online environment. Most of these problems occur in different online and local environments, and configuration is prone to errors. So what is the relationship between docker-compose and docker?

Let's first look at the definition of docker-compose:
Defining and running multi-container Docker applications

We know that docker can define an application container through a Dockerfile template file. In practical application, it is often encountered that multiple containers cooperate to run a set of applications. For example, in order to implement a Flask application, besides Flask service itself, some database service containers are needed. Compose satisfies this requirement. It allows users to define a set of associated application containers as a project through a separate docker-compose.yml template file (YAML format).
_Through Docker-Compose users can easily define a multi-container application with a configuration file, and then install all the dependencies of the application with a single instruction to complete the construction. Docker-Compose solves the problem of how to manage the layout between containers.

Implementation steps

Using Dockerfile to customize the image

Mirror customization is actually customizing the configuration and files added to each layer, because Flask applications need some environment dependency to run. So to run Flask applications in a Docker container, the container must install all the environment dependencies of the application. Dockerfile provides us with operations such as configuring environment dependencies. Dockerfile is a text file, which contains instructions. Each instruction builds a layer, so the content of each instruction is to describe how the layer should be constructed.

Here's my GitHub project flask-v2ex For example, the application Dockerfile file:

FROM daocloud.io/python:3.5

MAINTAINER Guoweikuang <guoweikuang2015@gmail.com>
RUN mkdir -p /home/guoweikuang/app 
WORKDIR /home/guoweikuang/app 

ADD ./requirements.txt /home/guoweikuang/app/requirements.txt 

RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip 
RUN pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt 

ADD . /home/guoweikuang/app 

CMD python manage.py runserver -h 0.0.0.0

FROM: Specifies the base image on which to customize the operation
MAINTAINER: Used to specify image creator information
RUN: Created **/home/guoweikuang/app** Folder (behind RUN pip3 install Python expanded memory bank)
WORKDIR: Switch directories, you can switch multiple times(Amount to cd command)
ADD: Copy files from local directory to container path
CMD: Set up container Operations performed at startup, run Flask Apply and set host For 0.0.0.0

Write docker-compose.yml file

The docker-compose.yml file will associate everything. It describes the composition of the application (a web service and a database), the Docker image used, the connection between the images, the volume mounted to the container, and the open ports of the service.

Here's my GitHub project flask-v2ex Take the docker-compose.yml file as an example:

version: '2'

services:
  web:
    build: .
    container_name: flask_v2ex
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"

Two service web and redis are defined in compose.

  • web Services

    • Build: Mirror the Docker file build using the current directory
    • Ports: Mapping host 5000 ports to container 5000 ports
    • container_name: Specifies the name of the container
  • redis services

    • Image: Using the redis image in Docker Hub

Build and run Flask applications using compose

Before running docker-composeup, you need to make some changes to the redis connection configuration in the project

r = redis.Redis(host='localhost', port=6379, decode_responses=True)

//Revised to:

r = redis.Redis(host='redis', port=6379, decode_responses=True)

Use the docker-compose up command in the root directory of the flask-v2ex project, as follows:

$ docker-compose up

Starting flask_v2ex         ... done
Starting flask_v2ex_redis_1 ... done
Attaching to flask_v2ex_redis_1, flask_v2ex
redis_1  | 1:C 01 Jul 07:46:52.053 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 01 Jul 07:46:52.053 # Redis version=4.0.6, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 01 Jul 07:46:52.053 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 01 Jul 07:46:52.064 * Running mode=standalone, port=6379.
redis_1  | 1:M 01 Jul 07:46:52.064 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
redis_1  | 1:M 01 Jul 07:46:52.064 # Server initialized
redis_1  | 1:M 01 Jul 07:46:52.065 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
redis_1  | 1:M 01 Jul 07:46:52.065 * DB loaded from disk: 0.000 seconds
redis_1  | 1:M 01 Jul 07:46:52.065 * Ready to accept connections
flask_v2ex |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
flask_v2ex |  * Restarting with stat
flask_v2ex |  * Debugger is active!
flask_v2ex |  * Debugger PIN: 742-073-002

You can see that the Docker daemon is listening for 5000 ports. Can pass http://localhost 5000 access Flask applications.

docker-compose uses

  • Docker-compose up-d: Background running
  • docker-compose stop: Stop running services
  • docker-compose down: Close all containers and delete them, leaving data volumes by default
  • docker-compose ps: Lists the current running service status and related information
$ docker-compose ps
       Name                     Command               State           Ports
------------------------------------------------------------------------------------
flask_v2ex           /bin/sh -c python manage.p ...   Up      0.0.0.0:5000->5000/tcp
flask_v2ex_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp
  • docker-compose run: One-time command. For example, look at the environment variables of web services:
$ docker-compose run web env 

PATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e4b6b17f39dc
TERM=xterm
LANG=C.UTF-8
GPG_KEY=97FC712E4C024BBEA48A61ED3A5CA953F73C700D
PYTHON_VERSION=3.5.4
PYTHON_PIP_VERSION=9.0.1
HOME=/root

If you need to stop a running service, you can stop the service by ctrl + c or docker-compose stop.

Reference resources

Docker from Introduction to Practice--Actual Django
Building Docker Image with Dockerfile

Topics: Python Docker Redis less