Skip to content

Commit 5844173

Browse files
committed
init draft
1 parent 8a4bc9b commit 5844173

File tree

6 files changed

+250
-1
lines changed

6 files changed

+250
-1
lines changed

Dockerfile

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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

README.md

+155-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,155 @@
1-
# python-app-docker-demo
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+
```

gunicorn.conf.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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'

main.py

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2015 Google Inc. All Rights Reserved.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# [START app]
16+
import logging
17+
18+
from flask import Flask, request, jsonify
19+
20+
app = Flask(__name__)
21+
22+
@app.route('/')
23+
def hello():
24+
"""Return a friendly HTTP greeting."""
25+
return 'Hello World'
26+
27+
@app.errorhandler(500)
28+
def server_error(e):
29+
logging.exception('An error occurred during a request.')
30+
return """
31+
An internal error occurred: <pre>{}</pre>
32+
See logs for full stacktrace.
33+
""".format(e), 500
34+
35+
if __name__ == '__main__':
36+
app.run(host='0.0.0.0', port=8081)

main.pyc

972 Bytes
Binary file not shown.

requirements.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Flask==0.10.1
2+
gunicorn==19.6.0
3+
futures==3.0.5

0 commit comments

Comments
 (0)