├── .gitignore ├── Dockerfile ├── README.md ├── app.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | FROM python:3.8-slim-buster 3 | 4 | WORKDIR /app 5 | 6 | COPY requirements.txt requirements.txt 7 | 8 | RUN pip3 install -r requirements.txt 9 | 10 | COPY . . 11 | 12 | CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0"] 13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python Flask Docker image 2 | 3 | [![type](https://img.shields.io/badge/type-Docker-blue.svg)](https://hub.docker.com/r/devilbox/python-flask) 4 | [![License](https://img.shields.io/badge/license-MIT-%233DA639.svg)](https://opensource.org/licenses/MIT) 5 | 6 | This tutorial provides a steps for building and deploying Python Flask demo project. 7 | Code repository - [https://github.com/chandradeoarya/docker-flask](https://github.com/chandradeoarya/docker-flask) 8 | 9 | ## Docker image tags 10 | 11 | **Image name:** `chandradeoarya/hello-flask` 12 | 13 | ## Environment Variables 14 | 15 | | Variable | Required | Default | Description | 16 | | --------------------- | -------- | ------------ | ---------------------- | 17 | | `MYSQL_ROOT_PASSWORD` | Yes | Helloflask@1 | mysql default password | 18 | 19 | ## Project directory structure 20 | 21 | The following shows how to organize your project on the host operating system. 22 | 23 | ### Basic structure 24 | 25 | The following is the least required directory structure: 26 | 27 | ```bash 28 | / 29 | └── app.py # Entrypoint file name can be changed via env var 30 | ``` 31 | 32 | ### Structure with dependencies 33 | 34 | The following directory structure allows for auto-installing Python dependencies during startup into a virtual env. 35 | 36 | ```bash 37 | / 38 | ├── app # Entrypoint dir name can be changed via env var 39 | │ ├── __init__.py 40 | │ └── main.py # Entrypoint file name can be changed via env var 41 | └── requirements.txt # Optional: will pip install in virtual env 42 | ``` 43 | 44 | After you've started the container with a `requirements.txt` in place, a new `venv/` directory will be added with you Python virtual env. 45 | 46 | ```bash 47 | / 48 | ├── app 49 | ├── __init__.py 50 | ├── main.py 51 | │ └── __pycache__ 52 | ├── requirements.txt 53 | └── venv 54 | ├── bin 55 | ├── include 56 | └── lib 57 | ``` 58 | 59 | ### Step-1 Building and running flask app image 60 | 61 | For building the images you need to go inside your project directory `hello-flask/` : 62 | 63 | ```bash 64 | # Clone the repository if not done yet 65 | git clone https://github.com/chandradeoarya/docker-flask.git 66 | 67 | # Pull step-1 code 68 | git pull origin master 69 | 70 | docker build --tag hello-flask . 71 | ``` 72 | 73 | You can tag image builds based on versions: 74 | 75 | ```bash 76 | docker tag hello-flask:latest hello-flask:v1 77 | # to remove a tag 78 | docker rmi hello-flask:v1 79 | ``` 80 | 81 | Now you have 82 | 83 | ```bash 84 | docker tag hello-flask:latest hello-flask:v1 85 | ``` 86 | 87 | Run a container based on this image 88 | 89 | ```bash 90 | docker run -d --name hello-flask-c --publish 5000:5000 hello-flask 91 | ``` 92 | 93 | ## Step-2 Adding mysql database in flask 94 | 95 | We will use docker official image for MySQL and run it in a container. Before we run MySQL in a container, we’ll create a couple of volumes that Docker can manage to store our persistent data and configuration. 96 | 97 | We are going to use volumes instead of bind mounts. 98 | 99 | ```bash 100 | # Pull step-2 code 101 | git pull origin step2 102 | 103 | # Create docker volume 104 | docker volume create hello-flask-mysql 105 | 106 | # Create docker volume for mysql configurations 107 | docker volume create hello-flask-mysql-config 108 | ``` 109 | 110 | Now we’ll create a network that our application and database will use to talk to each other. This will be a user-defined bridge network which gives a nice DNS lookup service which we can use when creating our connection string. 111 | 112 | ``` 113 | docker network create hello-flask-network 114 | ``` 115 | 116 | Now we can run MySQL in a container and attach to the volumes and network we created above. Docker pulls the image from Hub and runs it for you locally. In the following command, option -v is for starting the container with volumes. For more information, see Docker volumes. 117 | 118 | ``` 119 | docker run --rm -d -v hello-flask-mysql:/var/lib/mysql \ 120 | -v hello-flask-mysql-config:/etc/mysql -p 3306:3306 \ 121 | --network hello-flask-network \ 122 | --name helloflasksqldb \ 123 | -e MYSQL_ROOT_PASSWORD=Helloflask@1 \ 124 | mysql 125 | ``` 126 | 127 | Now, let’s test whether MySQL database is running and we can connect to it. Enter correct password when prompted: 128 | 129 | ``` 130 | docker exec -ti helloflasksqldb mysql -u root -p 131 | ``` 132 | 133 | Build docker image with mysql in flask 134 | 135 | ``` 136 | docker build --tag hello-flask-mysql . 137 | 138 | #Run the new flask app with mysql 139 | docker run --rm -d --network hello-flask-network --name hello-flask-mysql-c --publish 5000:5000 hello-flask-mysql 140 | 141 | # Db connection test and getting table entries 142 | curl http://localhost:5000 143 | curl http://localhost:5000/initdb 144 | curl http://localhost:5000/widgets 145 | 146 | # Insert some data in mysql inventory.widgets table 147 | docker exec -ti helloflasksqldb mysql -u root -p 148 | 149 | insert into inventory.widgets (name, description) values ('flask','simple python webapi'); 150 | insert into inventory.widgets (name, description) values ('docker','best containerization tool'); 151 | insert into inventory.widgets (name, description) values ('mysql','best database service'); 152 | ``` 153 | 154 | ## Step-3 Using Docker compose 155 | 156 | ```bash 157 | # Pull step-3 code 158 | git pull origin step3 159 | 160 | # Docker compose up 161 | docker-compose -f docker-compose.dev.yml up --build 162 | ``` 163 | 164 | ## License 165 | 166 | **[MIT License](LICENSE)** 167 | 168 | Copyright (c) 2021 [chandradeoarya(https://github.com/chandradeoarya)] 169 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | from flask import Flask 2 | app=Flask(__name__) 3 | 4 | @app.route('/') 5 | def hello_flask(): 6 | return 'Hello flask\n' -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click==8.0.1 2 | Flask==2.0.1 3 | itsdangerous==2.0.1 4 | Jinja2==3.0.1 5 | MarkupSafe==2.0.1 6 | Werkzeug==2.0.1 7 | --------------------------------------------------------------------------------