Docker/Podman使用提高---docker-compose基础(python3)

轩辕源
2023-12-01






1.docker-compose是什么

  • Docker Compose 是一个工具,命令行工具。
  • 这个工具可以通过yml文件定义多容器的docker应用
  • 通过一条命令就可以根据yml文件的定义去创建或者管理这多个容器



2.官方案例:python_web + redis 项目

step1: 创建文件夹


mkdir composetest
cd composetest

step2: 创建python文件,app.py,输入里面的内容如下:

import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)		# 此处连接的是容器名称,后续有redis集群,也连接的是集群名称

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')				# 这个函数啥东东?下面会讲
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)

step3: 创建requirements.txt文件, 输入里面的内容如下:


flask
redis

step4: 创建Dockerfile文件, 输入里面的内容如下:


FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py						# 这里是否可以不用设置
ENV FLASK_RUN_HOST=0.0.0.0					# 这里是否可以不用设置
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]						# 为啥要使用flask run 而不是python3 app.py??后面说到

step5: 创建docker-compose.yml文件, 输入里面的内容如下:


version: "3.9"
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis:alpine"				# 这里的redis,就是容器启动后的名称

step6: 启动docker-compose up .


[root@10-23-51-219 composetest]# docker-compose up
Building web


Step 1/10 : FROM python:3.7-alpine
 ---> 79d8d54b1857
Step 2/10 : WORKDIR /code
 ---> Using cache
 ---> 9eb6495ea257
Step 3/10 : ENV FLASK_APP app.py
 ---> Using cache
 ---> 15e7277f57f3
Step 4/10 : ENV FLASK_RUN_HOST 0.0.0.0
 ---> Using cache
 ---> 57a4af5435e8
Step 5/10 : RUN echo -e http://mirrors.ustc.edu.cn/alpine/v3.7/main/ > /etc/apk/repositories
 ---> Using cache
 ---> eae158bf812e
Step 6/10 : COPY requirements.txt requirements.txt
 ---> eb041643c8e3
Removing intermediate container c53c92a22253
Step 7/10 : RUN pip install -r requirements.txt
 ---> Running in a627e281c5b6


Collecting flask
  Downloading Flask-1.1.2-py2.py3-none-any.whl (94 kB)
Collecting redis
  Downloading redis-3.5.3-py2.py3-none-any.whl (72 kB)
Collecting itsdangerous>=0.24
  Downloading itsdangerous-1.1.0-py2.py3-none-any.whl (16 kB)
Collecting Jinja2>=2.10.1
  Downloading Jinja2-2.11.3-py2.py3-none-any.whl (125 kB)
Collecting click>=5.1
  Downloading click-7.1.2-py2.py3-none-any.whl (82 kB)
Collecting Werkzeug>=0.15
  Downloading Werkzeug-1.0.1-py2.py3-none-any.whl (298 kB)
Collecting MarkupSafe>=0.23
  Downloading MarkupSafe-1.1.1.tar.gz (19 kB)
Building wheels for collected packages: MarkupSafe
  Building wheel for MarkupSafe (setup.py): started
  Building wheel for MarkupSafe (setup.py): finished with status 'done'
  Created wheel for MarkupSafe: filename=MarkupSafe-1.1.1-py3-none-any.whl size=12629 sha256=4882ae01e0a1d50b0f836df700813c945bced6a8e4e0bfd9718a79635560cbef
  Stored in directory: /root/.cache/pip/wheels/b9/d9/ae/63bf9056b0a22b13ade9f6b9e08187c1bb71c47ef21a8c9924
Successfully built MarkupSafe
Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, redis, flask
Successfully installed Jinja2-2.11.3 MarkupSafe-1.1.1 Werkzeug-1.0.1 click-7.1.2 flask-1.1.2 itsdangerous-1.1.0 redis-3.5.3
 ---> 6dc4a3381526
Removing intermediate container a627e281c5b6



Step 8/10 : EXPOSE 5000
 ---> Running in bba8382e87dc
 ---> 27e23e0ecac8
Removing intermediate container bba8382e87dc


Step 9/10 : COPY . .
 ---> cf8485c26c53
Removing intermediate container e7597a071556


Step 10/10 : CMD flask run
 ---> Running in 6e860518647c
 ---> a05ff568c639
Removing intermediate container 6e860518647c
Successfully built a05ff568c639


WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Pulling redis (redis:alpine)...
alpine: Pulling from library/redis
ba3557a56b15: Already exists
4f47664a3e94: Pull complete
f5c47feea59c: Pull complete
dd29ad3f8731: Pull complete
961a5851f331: Pull complete
24af1e6d2f46: Pull complete
Digest: sha256:5c0374e9d2af14c0fb5cf0406d6fe74220998f7ec0250de33344d8e2a3b46305
Status: Downloaded newer image for redis:alpine
Creating composetest_web_1   ... done
Creating composetest_redis_1 ... done
Attaching to composetest_redis_1, composetest_web_1


redis_1  | 1:C 25 Feb 2021 03:20:01.956 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis_1  | 1:C 25 Feb 2021 03:20:01.956 # Redis version=6.2.0, bits=64, commit=00000000, modified=0, pid=1, just started
redis_1  | 1:C 25 Feb 2021 03:20:01.956 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis_1  | 1:M 25 Feb 2021 03:20:01.957 * monotonic clock: POSIX clock_gettime
redis_1  | 1:M 25 Feb 2021 03:20:01.957 * Running mode=standalone, port=6379.
redis_1  | 1:M 25 Feb 2021 03:20:01.957 # Server initialized
redis_1  | 1:M 25 Feb 2021 03:20:01.957 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
redis_1  | 1:M 25 Feb 2021 03:20:01.957 * Ready to accept connections
web_1    |  * Serving Flask app "app.py"
web_1    |  * Environment: production
web_1    |    WARNING: This is a development server. Do not use it in a production deployment.
web_1    |    Use a production WSGI server instead.
web_1    |  * Debug mode: off
web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
web_1    | 172.18.0.1 - - [25/Feb/2021 03:22:26] "GET / HTTP/1.1" 200 -
web_1    | 113.31.115.41 - - [25/Feb/2021 03:24:00] "GET / HTTP/1.1" 200 -
web_1    | 180.166.147.10 - - [25/Feb/2021 03:24:22] "GET / HTTP/1.1" 200 -
web_1    | 180.166.147.10 - - [25/Feb/2021 03:24:22] "GET /favicon.ico HTTP/1.1" 404 -
redis_1  | 1:M 25 Feb 2021 04:20:02.041 * 1 changes in 3600 seconds. Saving...
redis_1  | 1:M 25 Feb 2021 04:20:02.042 * Background saving started by pid 12
redis_1  | 12:C 25 Feb 2021 04:20:02.043 * DB saved on disk
redis_1  | 12:C 25 Feb 2021 04:20:02.043 * RDB: 0 MB of memory used by copy-on-write
redis_1  | 1:M 25 Feb 2021 04:20:02.142 * Background saving terminated with success





3.docker-compose.yaml 文件的规范

详情可参考:
《docker-compose命令及yaml文件》
《Docker学习记录 - docker compose yaml文件详解》




4.CMD命令使用:flask run

  • 最初的时候,看到官方的CMD命令使用flask run,启动了程序感觉很懵逼。后来在pycharm上测试了一下,果然也成功了。

使用flask run命令,需要注意的地方:

  • flask run 启动flask项目,默认的flask的启动项目文件名为官方的app.py文件
  • 如果你的项目中,启动文件是run.py,那么需要先设置FLASK_APP=run.py环境变量,才能使用,否者失败
  • 使用flask run,启动文件中,不需要添加if name == 'main’这个main函数了
# 
if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)

CMD中, 使用python3 app.py命令:

  • app.py 文件中,需要添加如上的main函数的部分
  • 不需要设置环境变量FLASK_APP & FLASK_RUN_HOST了,因为在main函数中都设置好了



5.redis中incr()函数


import redis

# 创建连接池:可以减少频繁的连接、断开数据库的开销
pool = redis.ConnectionPool(host="xxxxx", port=xxxx, db=0, password="xxxx", decode_responses=True)

# 创建redis对象
cache = redis.StrictRedis(connection_pool=pool)

# redis存储页面点击次数在合适不过了
cache.incr("page_hits")

print(r.get("page_hits"))

redis中incr函数:

  • 如果我们想实现计数的功能:在这个过程中,如果有并发就可能导致计数错误,所以,更新文章访问量的代码都是需要加锁的,以防止同时修改。
  • Redis的所有操作都是原子性的,也就是说,不论多少个客户端在对一个key进行操作,你不必担心并发导致的类似错误,因为Redis在实现上已经对这类问题进行处理。
  • 每次调用incr(key_name)函数,redis都会计数一次,对应的value值加一
 类似资料: