Docker容器技術-建立一個簡單的Web應用

1、建立一個簡單的Web應用

1.identicon
基於某個值而自動產生的圖像,這個值是IP地址或用戶名的散列值。html

用途:
經過計算用戶名或IP地址的散列值,在網站上提供用於識別用戶的圖像,以及自動生成網站的favicon。python

2.建立一個基本網頁web

[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.利用現有鏡像redis

[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

改進版:docker

[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')

2、實現緩存功能

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

3、微服務

微服務:由多個獨立的小服務組成;
單一服務架構:該系統包含在一個單獨的大型的服務之中(dnmonster、redis和identidock使用同一種編程語言實現)。flask

優勢:緩存

  • 適合橫向擴展到多態機器
  • 輕鬆快速地被其餘效能更高且功能相同的服務替代
  • 若發生意外,可只對部分微服務進行回滾
  • 不一樣微服務能夠用不一樣的語言實現,使開發者更好適用任務語言

缺點:網絡

  • 分佈式組件所致使的額外開銷
  • 通訊必須經過網絡,而不是庫的調用
  • 服務編排和服務發現
相關文章
相關標籤/搜索