├── requirements.txt ├── main.pyc ├── main.py ├── Dockerfile ├── gunicorn.conf.py └── README.md /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask==0.10.1 2 | gunicorn==19.6.0 3 | futures==3.0.5 4 | -------------------------------------------------------------------------------- /main.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bennzhang/docker-demo-with-simple-python-app/HEAD/main.pyc -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from flask import Flask, request, jsonify 4 | 5 | app = Flask(__name__) 6 | 7 | @app.route('/') 8 | def hello(): 9 | """Return a friendly HTTP greeting.""" 10 | return 'Hello World' 11 | 12 | @app.errorhandler(500) 13 | def server_error(e): 14 | logging.exception('An error occurred during a request.') 15 | return """ 16 | An internal error occurred:
{}
17 | See logs for full stacktrace. 18 | """.format(e), 500 19 | 20 | if __name__ == '__main__': 21 | app.run(host='0.0.0.0', port=8080) 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:2.7 2 | 3 | # Creating Application Source Code Directory 4 | RUN mkdir -p /usr/src/app 5 | 6 | # Setting Home Directory for containers 7 | WORKDIR /usr/src/app 8 | 9 | # Installing python dependencies 10 | COPY requirements.txt /usr/src/app/ 11 | RUN pip install --no-cache-dir -r requirements.txt 12 | 13 | # Copying src code to Container 14 | COPY . /usr/src/app 15 | 16 | # Application Environment variables 17 | #ENV APP_ENV development 18 | ENV PORT 8080 19 | 20 | # Exposing Ports 21 | EXPOSE $PORT 22 | 23 | # Setting Persistent data 24 | VOLUME ["/app-data"] 25 | 26 | # Running Python Application 27 | CMD gunicorn -b :$PORT -c gunicorn.conf.py main:app 28 | -------------------------------------------------------------------------------- /gunicorn.conf.py: -------------------------------------------------------------------------------- 1 | #By default the multi-process version of the runtime is launched via the Gunicorn webserver and is configured to use gevent-based concurrency and a number of processes equal to the number of CPU cores available. 2 | 3 | #This can be changed by creating a file called gunicorn.conf.py in your applications root directory, which will override the default gunicorn.conf.py included with this project 4 | 5 | 6 | import multiprocessing 7 | 8 | # Use threaded workers. Thread-based concurrency is provided via the 'futures' 9 | # package. 'gevent' or other workers would be candidates, except that the ndb 10 | # library has its own concurrency model that conflicts with gevent and possibly 11 | # with similar approaches. 12 | worker_class = 'gthread' 13 | 14 | # Use a number of workers equal to the number of CPU cores available. 15 | # Reducing this number on a multicore instance will reduce memory consumption, 16 | # but will also reduce the app's ability to utilize all available CPU resources. 17 | #workers = multiprocessing.cpu_count() 18 | #workers = 8 # good 19 | workers = 2 # good 20 | 21 | # Use an arbitrary number of threads for concurrency. This will dictate the 22 | # maximum number of requests handled concurrently by EACH worker. 23 | threads = 25 24 | 25 | # Settings specific to the Managed VMs production environment such as "bind" 26 | # and "logfile" are set in the Dockerfile's ENTRYPOINT directive. 27 | 28 | # Store the process ID of gunicorn. Used for testing. 29 | pidfile = 'gunicorn_pid.txt' 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python-app-docker-demo 2 | This demo shows two steps: 3 | + Install `docker-ce` on Centos 7 4 | + Build and run a simple docker image with a python+flask+gunicorn web application. 5 | 6 | ## Install docker-ce on Centos 7 7 | Refer to https://docs.docker.com/engine/installation/linux/docker-ce/centos/ 8 | You can also find [other OS installation docs from here](https://docs.docker.com/engine/installation). 9 | 10 | #### Uninstall old versions 11 | ``` 12 | $ sudo yum remove docker \ 13 | docker-common \ 14 | docker-selinux \ 15 | docker-engine 16 | ``` 17 | 18 | #### Install using repository 19 | ``` 20 | sudo yum install -y yum-utils device-mapper-persistent-data lvm2 21 | sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo 22 | sudo yum install docker-ce 23 | sudo systemctl start docker 24 | sudo docker run hello-world 25 | ``` 26 | 27 | Other commands: 28 | + check docker status 29 | ``` 30 | sudo systemctl status docker.service 31 | ``` 32 | 33 | + stop docker 34 | ``` 35 | sudo systemctl stop docker 36 | ``` 37 | 38 | + uninstall docker-ce 39 | ``` 40 | sudo yum remove docker-ce 41 | ``` 42 | 43 | + remove all images, container, volumes 44 | ``` 45 | sudo rm -rf /var/lib/docker 46 | ``` 47 | 48 | ## Build/Run a simple python+flask docker web app 49 | 50 | #### Create the Dockerfile 51 | 52 | ``` 53 | FROM python:2.7 54 | 55 | # Creating Application Source Code Directory 56 | RUN mkdir -p /usr/src/app 57 | 58 | # Setting Home Directory for containers 59 | WORKDIR /usr/src/app 60 | 61 | # Installing python dependencies 62 | COPY requirements.txt /usr/src/app/ 63 | RUN pip install --no-cache-dir -r requirements.txt 64 | 65 | # Copying src code to Container 66 | COPY . /usr/src/app 67 | 68 | # Application Environment variables 69 | #ENV APP_ENV development 70 | ENV PORT 8080 71 | 72 | # Exposing Ports 73 | EXPOSE $PORT 74 | 75 | # Setting Persistent data 76 | VOLUME ["/app-data"] 77 | 78 | # Running Python Application 79 | CMD gunicorn -b :$PORT -c gunicorn.conf.py main:app 80 | ``` 81 | 82 | #### Build your image 83 | Normally, image name convention is something like: ` 84 | {company/application-name}:{version-number}`. In the demo, I just use `{application-name}:{version-number}` 85 | 86 | ``` 87 | sudo docker build -t my-python-app:1.0.1 . 88 | ``` 89 | 90 | #### check all docker images 91 | ``` 92 | $ sudo docker images 93 | REPOSITORY TAG IMAGE ID CREATED SIZE 94 | my-python-app 1.0.1 2b628d11ba3a 22 minutes ago 701.6 MB 95 | docker.io/python 2.7 b1d5c2d7dda8 13 days ago 679.3 MB 96 | docker.io/hello-world latest 05a3bd381fc2 5 weeks ago 1.84 kB 97 | ``` 98 | 99 | `2b628d11ba3a` is the image ID, some commands based on the ID. 100 | 101 | + tag 102 | ``` 103 | sudo docker tag 2b628d11ba3a my-python-app:1.0.1 104 | sudo docker tag 2b628d11ba3a my-python-app:latest 105 | ``` 106 | 107 | + remove image 108 | ``` 109 | $ sudo docker rmi --force 2b628d11ba3a 110 | ``` 111 | 112 | #### Run your image 113 | ``` 114 | $ sudo docker run -d -p 8080:8080 my-python-app:1.0.1 115 | ``` 116 | 117 | 118 | You can use `sudo docker ps` to list all running containers. 119 | ``` 120 | $ sudo docker ps 121 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 122 | 4de6041072b7 my-python-app:1.0.1 "/bin/sh -c 'gunicorn" 20 minutes ago Up 20 minutes 0.0.0.0:8080->8080/tcp elegant_kowalevski 123 | ``` 124 | 125 | `4de6041072b7` is the running container id. Some commands below are what you might need. 126 | 127 | + display logs in running container 128 | ``` 129 | $ sudo docker logs 4de6041072b7 130 | [2017-10-23 20:29:49 +0000] [7] [INFO] Starting gunicorn 19.6.0 131 | [2017-10-23 20:29:49 +0000] [7] [INFO] Listening at: http://0.0.0.0:8080 (7) 132 | [2017-10-23 20:29:49 +0000] [7] [INFO] Using worker: gthread 133 | [2017-10-23 20:29:49 +0000] [11] [INFO] Booting worker with pid: 11 134 | [2017-10-23 20:29:49 +0000] [12] [INFO] Booting worker with pid: 12 135 | 136 | ``` 137 | 138 | + stop your container 139 | ``` 140 | $ sudo docker stop 4de6041072b7 141 | ``` 142 | 143 | + login inside the container 144 | ``` 145 | $ sudo docker exec -it 4de6041072b7 /bin/sh 146 | # ls /usr/src/app 147 | Dockerfile README.md gunicorn.conf.py gunicorn_pid.txt main.py main.pyc requirements.txt 148 | # exit 149 | ``` 150 | 151 | #### Test your application 152 | ``` 153 | $ curl http://localhost:8080 154 | Hello World 155 | ``` 156 | --------------------------------------------------------------------------------