您的位置:首页 > 运维架构 > Docker

Docker容器技术-创建一个简单的Web应用

2017-11-02 14:06 615 查看

一、创建一个简单的Web应用

1.identicon
基于某个值而自动产生的图像,这个值是IP地址或用户名的散列值。

用途:
通过计算用户名或IP地址的散列值,在网站上提供用于识别用户的图像,以及自动生成网站的favicon。

2.创建一个基本网页

[root@bogon app]# cat identidock.py
from flask import Flask
app = Flask(__name__)

default_name = 'Xiaoda'

@app.route('/')
def mainpage():
name = default_name

header = '<html><head><title>Identidock</title></head><body>'
body = '''<form method="POST">
Hello <input type="text" name="name" value="{}">
<input type="submit" value="submit">
</form>
<p>You look like a:
<img src="/monster/monster.png"/>
'''.format(name)
footer = '</body></html>'

return header + body + footer

if __name__ == '__main__':
app.run(debug=True,host='0.0.0.0')

[root@bogon identidock]# cat docker-compose.yml
identidock:
build: .
ports:
- "6900:6900"
environment:
ENV: DEV
volumes:
- ./app:/app

[root@bogon identidock]# docker-compose up -d
Building identidock
Step 1/5 : FROM python:3.4
---> 9ff45ddb54e9
Step 2/5 : RUN pip install Flask==0.10.1 uWSGI==2.0.8
---> Using cache
---> bb39db2742b4
Step 3/5 : WORKDIR /app
---> Using cache
---> 7159f825056f
Step 4/5 : COPY app /app
---> b13830295303
Step 5/5 : CMD uwsgi --http 0.0.0.0:9090 --wsgi-file /app/identidock.py --callable app --stats 0.0.0.0:9191
---> Running in 8d69046d66d7
---> 92852ec52596
Removing intermediate container 8d69046d66d7
Successfully built 92852ec52596
Successfully tagged identidock_identidock:latest
WARNING: Image for service identidock was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating identidock_identidock_1 ...
Creating identidock_identidock_1 ... done

2.利用现有镜像

[root@bogon app]# cat identidock.py
from flask import Flask,Response
import requests

app = Flask(__name__)
default_name = 'Xiaoda'

@app.route('/')
def mainpage():
name = default_name

header = '<html><head><title>Identidock</title></head><body>'
body = '''<form method="POST">
Hello <input type="text" name="name" value="{}">
<input type="submit" value="submit">
</form>
<p>You look like a:
<img src="/monster/monster.png"/>
'''.format(name)
footer = '</body></html>'

return header + body + footer
@app.route('/monster/<name>')
def get_identicon(name):
r = requests.get('http://dnmonster:8080/monster/' + name + '?size=80')
image = r.content

return Respinse(image, mimetype='image/png')

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')

[root@bogon identidock]# cat Dockerfile.1031
FROM python:3.4

RUN groupadd -r uwsgi && useradd -r -g uwsgi uwsgi
RUN pip install Flask==0.10.1 uWSGI==2.0.8 requests==2.5.1
WORKDIR /app
COPY app /app

EXPOSE 9090 9191
USER uwsgi

CMD ["/cmd.sh"]

[root@bogon identidock]# docker build -t identidock .
Sending build context to Docker daemon  7.168kB
Step 1/5 : FROM python:3.4
---> 9ff45ddb54e9
Step 2/5 : RUN pip install Flask==0.10.1 uWSGI==2.0.8
---> Using cache
---> bb39db2742b4
Step 3/5 : WORKDIR /app
---> Using cache
---> 7159f825056f
Step 4/5 : COPY app /app
---> 3080bcfb4b16
Step 5/5 : CMD uwsgi --http 0.0.0.0:9090 --wsgi-file /app/identidock.py --callable app --stats 0.0.0.0:9191
---> Running in ea63b5069cc2
---> 3966bef511e5
Removing intermediate container ea63b5069cc2
Successfully built 3966bef511e5
Successfully tagged identidock:latest

[root@bogon identidock]# docker run -d --name dnmonster amouat/dnmonster:1.0
Unable to find image 'amouat/dnmonster:1.0' locally
1.0: Pulling from amouat/dnmonster
a3ed95caeb02: Pull complete
453d13af6c96: Pull complete
Digest: sha256:e9e991ffa0d05583af0ed0541d03c519d37762750c462bd86b3546f600e11231
Status: Downloaded newer image for amouat/dnmonster:1.0
4136951e5602ccb1939a0d47552b0fc9f2bf217baef640837e152cb09e5fdc11

[root@bogon identidock]# docker run -d -p 6800:6800 -e "ENV=DEV" --link dnmonster:dnmonster identidock
dd27f8941770b13b18a3b48157f440f91081a73655bc7ca25a11dcf1c244ddcb

改进版:

[root@bogon identidock]# cat docker-compose.yml
identidock:
build: .
ports:
- "6900:6900"
environment:
ENV: DEV
volumes:
- ./app:/app
links:
- dnmonster

dnmonster:
image: amouat/dnmonster:1.0

[root@bogon identidock]# docker rm $(docker stop $(docker ps -q))
dd27f8941770
4136951e5602
f0a6553a9c33

[root@bogon identidock]# docker-compose build
dnmonster uses an image, skipping
Building identidock
Step 1/5 : FROM python:3.4
---> 9ff45ddb54e9
Step 2/5 : RUN pip install Flask==0.10.1 uWSGI==2.0.8
---> Using cache
---> bb39db2742b4
Step 3/5 : WORKDIR /app
---> Using cache
---> 7159f825056f
Step 4/5 : COPY app /app
---> 4258a3f27a07
Step 5/5 : CMD uwsgi --http 0.0.0.0:9090 --wsgi-file /app/identidock.py --callable app --stats 0.0.0.0:9191
---> Running in 7898c0f79b37
---> 6eda3dd73c7a
Removing intermediate container 7898c0f79b37
Successfully built 6eda3dd73c7a
Successfully tagged identidock_identidock:latest

[root@bogon identidock]# docker-compose up -d
Creating identidock_dnmonster_1 ...
Creating identidock_dnmonster_1 ... done
Creating identidock_identidock_1 ...
Creating identidock_identidock_1 ... done

[root@bogon app]# cat identidock.py
from flask import Flask,Response
import requests
import hashlib

app = Flask(__name__)
salt = "UNIQUE_SALT"
default_name = 'Xiaoda'

@app.route('/')
def mainpage():
name = default_name

if request.method == 'POST':
name = request.form['name']

salted_name = salt + name
name_hash = hashlib.sha256(salted_name.encode()).hexdigest()

header = '<html><head><title>Identidock</title></head><body>'
body = '''<form method="POST">
Hello <input type="text" name="name" value="{}">
<input type="submit" value="submit">
</form>
<p>You look like a:
<img src="/monster/monster.png"/>
'''.format(name)
footer = '</body></html>'

return header + body + footer

@app.route('/monster/<name>')
def get_identicon(name):
r = requests.get('http://dnmonster:8080/monster/' + name + '?size=80')
image = r.content

return Respinse(image, mimetype='image/png')

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')

二、实现缓存功能

1.在一个容器中运行多个进程
使用进程管理器supervisord,负责进程的启动和监视。

[root@bogon app]# cat identidock.py
from flask import Flask,Response
import requests
import hashlib
import redis

app = Flask(__name__)
cache = redis.StrictRedis(host='redis',port=6379,db=0)
salt = "UNIQUE_SALT"
default_name = 'Xiaoda'

@app.route('/',methods=['GET','POST'])
def mainpage():
name = default_name

if request.method == 'POST':
name = request.form['name']

salted_name = salt + name
name_hash = hashlib.sha256(salted_name.encode()).hexdigest()

header = '<html><head><title>Identidock</title></head><body>'
body = '''<form method="POST">
Hello <input type="text" name="name" value="{}">
<input type="submit" value="submit">
</form>
<p>You look like a:
<img src="/monster/monster.png"/>
'''.format(name)
footer = '</body></html>'

return header + body + footer

@app.route('/monster/<name>')
def get_identicon(name):
image = cache.get(name)
if image is None:
print("Cache miss",flush=True)
r = requests.get('http://dnmonster:8080/monster/' + name + '?size=80')
image = r.content
cache.set(name,image)

return Respinse(image, mimetype='image/png')

if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
[root@bogon identidock]# cat Dockerfile.1031
FROM python:3.4

RUN groupadd -r uwsgi && useradd -r -g uwsgi uwsgi
RUN pip install Flask==0.10.1 uWSGI==2.0.8 requests==2.5.1 redis==2.10.6
WORKDIR /app
COPY app /app
COPY cmd.sh /

EXPOSE 9090 9191
USER uwsgi

CMD ["/cmd.sh"]
[root@bogon identidock]# cat docker-compose.yml
identidock:
build: .
ports:
- "7000:7000"
environment:
ENV: DEV
volumes:
- ./app:/app
links:
- dnmonster
- redis

dnmonster:
image: amouat/dnmonster:1.0

redis:
image: redis:3.0

[root@bogon identidock]# docker-compose build
dnmonster uses an image, skipping
redis uses an image, skipping
Building identidock
Step 1/9 : FROM python:3.4
---> 9ff45ddb54e9
Step 2/9 : RUN groupadd -r uwsgi && useradd -r -g uwsgi uwsgi
---> Using cache
---> 1aa7c9d755eb
Step 3/9 : RUN pip install Flask==0.10.1 uWSGI==2.0.8 requests==2.5.1 redis==2.10.6
---> Running in 107013f2d391
Collecting Flask==0.10.1
Downloading Flask-0.10.1.tar.gz (544kB)
Collecting uWSGI==2.0.8
Downloading uwsgi-2.0.8.tar.gz (775kB)
Collecting requests==2.5.1
Downloading requests-2.5.1-py2.py3-none-any.whl (464kB)
Collecting redis==2.10.6
Downloading redis-2.10.6-py2.py3-none-any.whl (64kB)
Collecting Werkzeug>=0.7 (from Flask==0.10.1)
Downloading Werkzeug-0.12.2-py2.py3-none-any.whl (312kB)
Collecting Jinja2>=2.4 (from Flask==0.10.1)
Downloading Jinja2-2.9.6-py2.py3-none-any.whl (340kB)
Collecting itsdangerous>=0.21 (from Flask==0.10.1)
Downloading itsdangerous-0.24.tar.gz (46kB)
Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->Flask==0.10.1)
Downloading MarkupSafe-1.0.tar.gz
Building wheels for collected packages: Flask, uWSGI, itsdangerous, MarkupSafe
Running setup.py bdist_wheel for Flask: started
Running setup.py bdist_wheel for Flask: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/b6/09/65/5fcf16f74f334a215447c26769e291c41883862fe0dc7c1430
Running setup.py bdist_wheel for uWSGI: started
Running setup.py bdist_wheel for uWSGI: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/04/43/f1/b6308e3b9ea71a31b9e5b69b6fe50bea89e852688bf46e8b92
Running setup.py bdist_wheel for itsdangerous: started
Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/fc/a8/66/24d655233c757e178d45dea2de22a04c6d92766abfb741129a
Running setup.py bdist_wheel for MarkupSafe: started
Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/88/a7/30/e39a54a87bcbe25308fa3ca64e8ddc75d9b3e5afa21ee32d57
Successfully built Flask uWSGI itsdangerous MarkupSafe
Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, Flask, uWSGI, requests, redis
Successfully installed Flask-0.10.1 Jinja2-2.9.6 MarkupSafe-1.0 Werkzeug-0.12.2 itsdangerous-0.24 redis-2.10.6 requests-2.5.1 uWSGI-2.0.8
---> 25710c7b3813
Removing intermediate container 107013f2d391
Step 4/9 : WORKDIR /app
---> 9178ae566c42
Removing intermediate container 541c592bf996
Step 5/9 : COPY app /app
---> 756498c4229c
Step 6/9 : COPY cmd.sh /
---> 67416d7b3c6b
Step 7/9 : EXPOSE 9090 9191
---> Running in e3fb71c7cb6a
---> e9c0c03315ad
Removing intermediate container e3fb71c7cb6a
Step 8/9 : USER uwsgi
---> Running in f952ebf8f50b
---> 732e703b3373
Removing intermediate container f952ebf8f50b
Step 9/9 : CMD /cmd.sh
---> Running in 9943687a5efa
---> 94f20e22970d
Removing intermediate container 9943687a5efa
Successfully built 94f20e22970d
Successfully tagged identidock_identidock:latest

[root@bogon identidock]# docker-compose up -d
Pulling redis (redis:3.0)...
3.0: Pulling from library/redis
f5cc0ee7a6f6: Pull complete
5fc25ed18e87: Pull complete
e025bc8872f6: Pull complete
77c68b51b836: Pull complete
7c403ece3755: Pull complete
0a653bd338f4: Pull complete
31531fd948c6: Pull complete
Digest: sha256:730b765df9fe96af414da64a2b67f3a5f70b8fd13a31e5096fee4807ed802e20
Status: Downloaded newer image for redis:3.0
Starting identidock_dnmonster_1 ...
Starting identidock_dnmonster_1
Creating identidock_redis_1 ...
Creating identidock_redis_1 ... done
Recreating identidock_identidock_1 ...
Recreating identidock_identidock_1 ... done

三、微服务

微服务:由多个独立的小服务组成;
单一服务架构:该系统包含在一个单独的大型的服务之中(dnmonster、redis和identidock使用同一种编程语言实现)。

优点:

  • 适合横向扩展到多态机器
  • 轻松快速地被其他效能更高且功能相同的服务替代
  • 若发生意外,可只对部分微服务进行回滚
  • 不同微服务可以用不同的语言实现,使开发者更好适用任务语言

缺点:

  • 分布式组件所导致的额外开销
  • 通信必须通过网络,而不是库的调用
  • 服务编排和服务发现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: