├── 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 |
--------------------------------------------------------------------------------