From a0bd253143238893e40db674194464b71c586c80 Mon Sep 17 00:00:00 2001 From: Jagger Wang Date: Sat, 3 Aug 2019 15:32:57 +0800 Subject: [PATCH] deploy app by docker --- README.md | 14 +++++----- .../friendly-hello/.dockerignore | 8 ++++++ docker-app-deploy/friendly-hello/.env | 1 + docker-app-deploy/friendly-hello/Dockerfile | 27 +++++++++++++++++++ docker-app-deploy/friendly-hello/app.py | 27 +++++++++++++++++++ .../friendly-hello/docker-compose.yml | 20 ++++++++++++++ .../friendly-hello/requirements.txt | 2 ++ .../multi-stage-build/Dockerfile | 5 ++++ .../multi-stage-build/Dockerfile.build | 5 ++++ .../multi-stage-build/Dockerfile.multi | 11 ++++++++ docker-app-deploy/multi-stage-build/build.sh | 14 ++++++++++ docker-compose.dev.yml | 10 +------ docker-compose.yml | 10 +++---- requirements.txt | 6 +++++ weiguan/config/base.py | 26 +++++++++--------- 15 files changed, 152 insertions(+), 34 deletions(-) create mode 100644 docker-app-deploy/friendly-hello/.dockerignore create mode 100644 docker-app-deploy/friendly-hello/.env create mode 100644 docker-app-deploy/friendly-hello/Dockerfile create mode 100644 docker-app-deploy/friendly-hello/app.py create mode 100644 docker-app-deploy/friendly-hello/docker-compose.yml create mode 100644 docker-app-deploy/friendly-hello/requirements.txt create mode 100644 docker-app-deploy/multi-stage-build/Dockerfile create mode 100644 docker-app-deploy/multi-stage-build/Dockerfile.build create mode 100644 docker-app-deploy/multi-stage-build/Dockerfile.multi create mode 100644 docker-app-deploy/multi-stage-build/build.sh diff --git a/README.md b/README.md index 79d2293..c72667b 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # Sanic in Practice -This project is the reference source code of online video course [叽歪课堂 - Python Sanic 高并发服务开发实战](https://blog.jaggerwang.net/python-sanic-high-currency-service-in-practice/), including Sanic web framework usage examples, SQLAlchemy sql toolkit usage examples, and a lite version of [Weiguan](https://weiguan.app/) app's server. +This project is the reference source code of online video course [叽歪课堂 - Python Sanic 高并发服务开发实战](https://blog.jaggerwang.net/python-sanic-high-currency-service-development/), including Sanic web framework usage examples, SQLAlchemy sql toolkit usage examples, and a lite version of [Weiguan](https://weiguan.app/) app's api server. -## Frameworks and libraries +## Frameworks and libraries used by this project 1. [Sanic](https://github.com/huge-success/sanic) Asynchronous web framework and server -1. [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy) SQL toolkit -1. [AIOMySQL](https://github.com/aio-libs/aiomysql) Asynchronous read from and write to mysql -1. [AIORedis](https://github.com/aio-libs/aioredis) Asynchronous read from and write to redis +1. [SQLAlchemy](https://github.com/sqlalchemy/sqlalchemy) SQL toolkit and orm framework +1. [AIOMySQL](https://github.com/aio-libs/aiomysql) Asynchronous access mysql +1. [AIORedis](https://github.com/aio-libs/aioredis) Asynchronous access redis 1. [MarshMallow](https://github.com/marshmallow-code/marshmallow/) Object serialization 1. [Fire](https://github.com/google/python-fire) CLI application framework 1. [APScheduler](https://github.com/agronholm/apscheduler) Run interval jobs @@ -76,7 +76,7 @@ Change the content of `docker-compose.yml` as needed, especially the host path o docker-compose up ``` -It will start server, scheduler, mysql and redis services. If you need to stop all services, you can execute command `docker-compose down`. +It will start server, scheduler, mysql and redis services. If you need to stop and remove all services, you can execute command `docker-compose down`. The server and scheduler services will start failed before creating the project's database, you should run `docker-compose up` again after created the database. #### Create database and tables @@ -89,7 +89,7 @@ $ mysql -u root -p > GRANT ALL PRIVILEGES ON `weiguan`.* TO 'weiguan'@'%' IDENTIFIED BY 'jwcourse.com'; ``` -Second, login to server container and create tables of this project. +Second, login to server container and create tables for this project. ```bash docker container exec -it sanic-in-practice_server_1 bash diff --git a/docker-app-deploy/friendly-hello/.dockerignore b/docker-app-deploy/friendly-hello/.dockerignore new file mode 100644 index 0000000..74e2d8a --- /dev/null +++ b/docker-app-deploy/friendly-hello/.dockerignore @@ -0,0 +1,8 @@ +# comment + +*/temp* +*/*/temp* +temp? + +*.md +!README.md \ No newline at end of file diff --git a/docker-app-deploy/friendly-hello/.env b/docker-app-deploy/friendly-hello/.env new file mode 100644 index 0000000..5f7235f --- /dev/null +++ b/docker-app-deploy/friendly-hello/.env @@ -0,0 +1 @@ +KEY=value \ No newline at end of file diff --git a/docker-app-deploy/friendly-hello/Dockerfile b/docker-app-deploy/friendly-hello/Dockerfile new file mode 100644 index 0000000..1eb5a31 --- /dev/null +++ b/docker-app-deploy/friendly-hello/Dockerfile @@ -0,0 +1,27 @@ +# escape=\ + +# Use latest python +FROM python + +# Build args +ARG user +ARG buildno=1 + +# Set environment variables +ENV NAME World +ENV WORKDIR /app + +# Set current working directory +WORKDIR ${WORKDIR} + +# Copy all files in current directory on host into container +COPY . /app + +# Install pip packages +RUN pip install -i https://mirrors.aliyun.com/pypi/simple/ -r requirements.txt + +# Inform others the listening port of service in container +EXPOSE 80 + +# Which command to run when start a container +CMD ["python", "app.py"] \ No newline at end of file diff --git a/docker-app-deploy/friendly-hello/app.py b/docker-app-deploy/friendly-hello/app.py new file mode 100644 index 0000000..a21285e --- /dev/null +++ b/docker-app-deploy/friendly-hello/app.py @@ -0,0 +1,27 @@ +from flask import Flask +from redis import Redis, RedisError +import os +import socket + +redis = Redis(host='redis', socket_connect_timeout=1, socket_timeout=1) + +app = Flask(__name__) + + +@app.route("/") +def hello(): + try: + visits = redis.incr('counter') + except RedisError: + visits = "cannot connect to Redis, counter disabled" + + html = '''

Hello {name}!

+Hostname: {hostname}
+Visits: {visits} +''' + return html.format(name=os.getenv('NAME', 'world'), + hostname=socket.gethostname(), visits=visits) + + +if __name__ == '__main__': + app.run(host='0.0.0.0', port=8000) diff --git a/docker-app-deploy/friendly-hello/docker-compose.yml b/docker-app-deploy/friendly-hello/docker-compose.yml new file mode 100644 index 0000000..1a675b9 --- /dev/null +++ b/docker-app-deploy/friendly-hello/docker-compose.yml @@ -0,0 +1,20 @@ +version: '3' +services: + web: + build: . + image: friendly-web + ports: + - 8001:8000 + networks: + - friendly-net + redis: + image: redis + ports: + - 6380:6379 + volumes: + - ~/data/friendly-hello/redis:/data + command: redis-server --appendonly yes + networks: + - friendly-net +networks: + friendly-net: \ No newline at end of file diff --git a/docker-app-deploy/friendly-hello/requirements.txt b/docker-app-deploy/friendly-hello/requirements.txt new file mode 100644 index 0000000..8862084 --- /dev/null +++ b/docker-app-deploy/friendly-hello/requirements.txt @@ -0,0 +1,2 @@ +Flask +Redis \ No newline at end of file diff --git a/docker-app-deploy/multi-stage-build/Dockerfile b/docker-app-deploy/multi-stage-build/Dockerfile new file mode 100644 index 0000000..c06ff64 --- /dev/null +++ b/docker-app-deploy/multi-stage-build/Dockerfile @@ -0,0 +1,5 @@ +FROM alpine:latest +RUN apk --no-cache add ca-certificates +WORKDIR /root/ +COPY app . +CMD ["./app"] \ No newline at end of file diff --git a/docker-app-deploy/multi-stage-build/Dockerfile.build b/docker-app-deploy/multi-stage-build/Dockerfile.build new file mode 100644 index 0000000..aeb9ec4 --- /dev/null +++ b/docker-app-deploy/multi-stage-build/Dockerfile.build @@ -0,0 +1,5 @@ +FROM golang:1.7.3 +WORKDIR /go/src/github.com/alexellis/href-counter/ +COPY app.go . +RUN go get -d -v golang.org/x/net/html \ + && CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . \ No newline at end of file diff --git a/docker-app-deploy/multi-stage-build/Dockerfile.multi b/docker-app-deploy/multi-stage-build/Dockerfile.multi new file mode 100644 index 0000000..4b15434 --- /dev/null +++ b/docker-app-deploy/multi-stage-build/Dockerfile.multi @@ -0,0 +1,11 @@ +FROM golang:1.7.3 AS builder +WORKDIR /go/src/github.com/alexellis/href-counter/ +RUN go get -d -v golang.org/x/net/html +COPY app.go . +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . + +FROM alpine:latest +RUN apk --no-cache add ca-certificates +WORKDIR /root/ +COPY --from=builder /go/src/github.com/alexellis/href-counter/app . +CMD ["./app"] \ No newline at end of file diff --git a/docker-app-deploy/multi-stage-build/build.sh b/docker-app-deploy/multi-stage-build/build.sh new file mode 100644 index 0000000..61e5b13 --- /dev/null +++ b/docker-app-deploy/multi-stage-build/build.sh @@ -0,0 +1,14 @@ +#!/bin/sh +echo Building alexellis2/href-counter:build + +docker build --build-arg https_proxy=$https_proxy --build-arg http_proxy=$http_proxy \ + -t alexellis2/href-counter:build . -f Dockerfile.build + +docker container create --name extract alexellis2/href-counter:build +docker container cp extract:/go/src/github.com/alexellis/href-counter/app ./app +docker container rm -f extract + +echo Building alexellis2/href-counter:latest + +docker build --no-cache -t alexellis2/href-counter:latest . +rm ./app \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 767489d..71c6924 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -4,18 +4,10 @@ services: build: . command: sleep infinity volumes: - - ~/data/weiguan/server:/data - .:/workspace - ~/.ssh:/root/.ssh-localhost:ro scheduler: build: . command: sleep infinity volumes: - - ~/data/weiguan/scheduler:/data - - .:/workspace - mysql: - volumes: - - ~/data/weiguan/mysql:/var/lib/mysql - redis: - volumes: - - ~/data/weiguan/redis:/data \ No newline at end of file + - .:/workspace \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6860c7f..fe97cb3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,9 +14,9 @@ services: WG_MYSQL_PASSWORD: jwcourse.com WG_REDIS_URI: redis://@redis:6379/0 ports: - - "8001:8000" + - 8001:8000 volumes: - - /data/weiguan/server:/data + - ~/data/weiguan-demo/server:/data scheduler: image: weiguan command: python -u -m weiguan.manage schedule run @@ -32,18 +32,18 @@ services: WG_MYSQL_PASSWORD: jwcourse.com WG_REDIS_URI: redis://@redis:6379/0 volumes: - - /data/weiguan/scheduler:/data + - ~/data/weiguan-demo/scheduler:/data mysql: image: mysql:5.7 environment: TZ: Asia/Shanghai MYSQL_ROOT_PASSWORD: jwcourse.com volumes: - - /data/weiguan/mysql:/var/lib/mysql + - ~/data/weiguan-demo/mysql:/var/lib/mysql redis: image: redis:5 environment: TZ: Asia/Shanghai volumes: - - /data/weiguan/redis:/data + - ~/data/weiguan-demo/redis:/data \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 476307d..223359e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,8 +9,10 @@ autopep8==1.4.4 certifi==2019.6.16 cffi==1.12.3 chardet==3.0.4 +Click==7.0 cryptography==2.7 fire==0.1.3 +Flask==1.1.1 h11==0.8.1 h2==3.1.0 hiredis==1.0.0 @@ -20,7 +22,10 @@ httptools==0.0.13 hyperframe==5.2.0 idna==2.8 isort==4.3.21 +itsdangerous==1.1.0 +Jinja2==2.10.1 lazy-object-proxy==1.4.1 +MarkupSafe==1.1.1 marshmallow==3.0.0rc8 mccabe==0.6.1 multidict==4.5.2 @@ -43,4 +48,5 @@ ujson==1.35 urllib3==1.25.3 uvloop==0.12.2 websockets==6.0 +Werkzeug==0.15.5 wrapt==1.11.2 diff --git a/weiguan/config/base.py b/weiguan/config/base.py index af223aa..3b1a629 100644 --- a/weiguan/config/base.py +++ b/weiguan/config/base.py @@ -1,29 +1,29 @@ NAME = 'weiguan' -# 运行时数据保存路径,比如日志、上传文件等 +# Directory of runtime data, like logs and uploaded files etc DATA_PATH = '/tmp' -# 上传文件子目录 +# Subdirectory of uploaded files UPLOAD_DIR = 'uploads' -# 服务监听地址和端口 +# Listen host and port of server HOST = '0.0.0.0' PORT = 8000 -# 是否为调试模式 +# Whether in debug mode DEBUG = True -# 是否热加载代码 +# Whether to auto load modified code AUTO_RELOAD = True -# 是否记录访问日志 +# Whether log access record ACCESS_LOG = True -# 工作进程数 +# Number of working processes WORKERS = 1 -# 会话有效期 +# Valid seconds of session SESSION_EXPIRY = 30 * 24 * 3600 -# 请求体大小限制 +# Max size of request in bytes REQUEST_MAX_SIZE = 100 * 1024 * 1024 -# 上传文件大小限制 +# Max allowed size of uploaded file in bytes UPLOAD_FILE_MAX_SIZE = 50 * 1024 * 1024 -# 上传文件访问域名 +# Endpoint of uploaded files UPLOAD_FILE_URL_BASE = 'http://localhost:8000/files/' -# MySQL连接信息 +# MySQL connection parameters MYSQL_HOST = 'localhost' MYSQL_PORT = 3306 MYSQL_DB = 'weiguan_demo' @@ -33,7 +33,7 @@ MYSQL_POOL_MIN_SIZE = 1 MYSQL_POOL_MAX_SIZE = 100 -# Redis连接信息 +# Redis connection parameters REDIS_URI = 'redis://@localhost:6379/0' REDIS_TIMEOUT = 1 REDIS_POOL_MIN_SIZE = 1