Docker Compose 的使用
在上一节中,我们了解了将 Scrapy 项目打包为 Docker 镜像的方式,不过其中有一些不太方便的地方。
-
构建镜像的命令比较烦琐而且难以记忆,比如需要额外添加一些配置选项。
-
如果需要同时启动多个 Docker 容器协同运行,仅使用 docker run 命令是难以实现的。
下面我们再来介绍一个工具 Docker Compose,使用它,我们可以方便地实现镜像的打包、容器的协同管理。
Docker Compose
Docker Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过它,我们可以使用 YAML 格式的文件来配置程序需要的所有服务,比如 YAML 文件里面定义了构建的目标镜像名称、容器启动的端口、环境变量设置等,把这些固定的内容配置到 YAML 文件之后,我们只需要使用简单的 docker-compose 命令就可以实现镜像的构建和容器的启动,非常方便。
接下来,我们将尝试利用 Docker Compose 来构建上一节介绍的镜像吧。
准备工作
首先,我们需要准备好上一节学习的所有内容,包括 ScrapyCompositeDemo 的代码以及对应的 Dockerfile,能正常构建 Docker 镜像。另外,我们还需要准备好账号池、代理池并能成功运行。
除了如上内容外,我们还需要安装好 Docker Compose,安装方法可以参考:https://setup.scrape.center/docker-compose。安装好之后,我们就可以使用 docker-compose 命令了。
创建 YAML 文件
首先,我们需要确保代理池在本级的 5555 端口上正常运行,账号池在本级的 6777 端口上正常运行,具体的内容可以参考 15.13 节。
接下来,我们在 ScrapyCompositeDemo 根目录下创建一个 docker-compose.yaml 文件,内容如下:
version: "3"
services:
redis:
image: redis:alpine
container_name: redis
ports:
- "6379"
scrapycompositedemo:
build: "."
image: "germey/scrapycompositedemo"
environment:
ACCOUNTPOOL_URL: "http://host.docker.internal:6777/antispider?random"
PROXYPOOL_URL: "http://host.docker.internal:5555/random"
REDIS_HOST: "redis://redis:6379"
depends_on:
- redis
首先,第一行我们指定了 version,其值为 3,即 Docker Compose 的版本信息。目前,绝大多数情况下都将其指定为 3。
然后我们指定 services 的配置,一个是 redis,一个是 scrapycompositedemo,即启动的两个服务一个是 Redis 数据库,一个是我们 的 Scrapy 爬虫项目 ScrapyCompositeDemo。
对于 Redis 来说,我们直接使用了已有的镜像来构建,所以直接指定了 image 字段,内容为 redis:alpine,这是一个公开镜像,直接下载并运行即可启动一个 Redis 服务。接下来,我们指定了 container_name,即 redis:alpine 这个镜像启动之后的容器名称,我们就直接赋值为 redis 即可。当然,也可以替换其他的名称。然后就是运行端口,这里我们直接指定了运行端口 6379。
对于 Scrapy 爬虫项目来说,由于代码在本地,所以构建位置就直接指定为 .,代表当前目录。接着,我们指定了构建的目标镜像名称,这里就直接指定为我的 Docker Hub 为该项目配置的镜像地址 germey/scrapycompositedemo,其中 germey 是我的 Docker Hub 用户名,这里请自行替换成你的用户名。接下来,我们利用 environment 来指定环境变量,还是上一节所述的内容。另外,我们还指定了 depends_on 配置,内容为 redis,即该容器的启动需要依赖于刚才声明的 redis 服务,这样只有等 redis 对应的容器正常启动之后,该容器才会启动。
|
如果你想了解更多 Docker Compose 的配置选项,可以参考 Docker Compose 的官方文档: https://docs.docker.com/compose/。 |
构建镜像
接下来,我们就可以利用 docker-compose 命令来构建 Docker 镜像了。在 docker-compose.yaml 目录下运行该命令即可:
docker-compose build
运行结果类似如下:
redis uses an image, skipping
Building scrapycompositedemo
[+] Building 2.7s (11/11) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 37B
=> [internal] load .dockerignore
=> => transferring context: 2B
=> [internal] load metadata for docker.io/library/python:3.7
=> [auth] library/python:pull token for registry-1.docker.io
=> [1/5] FROM docker.io/library/python:3.7@sha256:0ba96071fe70b9cf6dd2247f7901e35961cba04459933c4301ad6a5930f9c2b9
=> [internal] load build context
=> => transferring context: 37.08kB
=> [2/5] CACHED [2/5] WORKDIR /app
=> [3/5] CACHED [4/5] RUN pip install -U pip & pip install -r requirements.txt
=> [5/5] COPY . .
=> exporting to image
=> => exporting layers
=> => writing image sha256:b2f3f35e9e51f2b38eabc70c3a6a5foeff1e8409a86e05259685b2ebb736515b
=> naming to docker.io/germey/scrapycompositedemo
这里就输出了构建镜像的整个过程,和上一节构建的过程非常相似,只不过我们不用再关心怎样指定镜像名称,不用指定构建路径了。
运行镜像
运行镜像也是十分简单的,我们也无须再指定环境变量、容器名称、容器运行端口等内容,只需要一条命令就可以一下予启动 redis 和 scrapycompositedemo 这两个服务:
docker-compose up
运行结果如下:
Starting redis ... done
Recreating scrapycompositedemo_scrapycompositedemo_1 ... done
Attaching to redis, scrapycompositedemo_scrapycompositedemo_1
redis | 1:C 31 Jul 2021 18:29:10.828 # oO0O0O0O0O0O0 Redis is starting oO0O0O0O0O0O0
redis | 1:C 31 Jul 2021 18:29:10.828 # Redis version=6.2.3, bits=64, commit=00000000, modified=0, pid=1, just started
redis | 1:C 31 Jul 2021 18:29:10.828 # 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:M 31 Jul 2021 18:29:10.829 * monotonic clock: POSIX clock_gettime
redis | 1:M 31 Jul 2021 18:29:10.829 * Running mode=standalone, port=6379.
redis | 1:M 31 Jul 2021 18:29:10.830 # Server initialized
redis | 1:M 31 Jul 2021 18:29:10.830 * Ready to accept connections
scrapycompositedemo_1 | 2021-07-31 18:29:13 [scrapy.utils.log] INFO: Scrapy 2.5.0 started (bot: scrapycompositedemo)
scrapycompositedemo_1 | 2021-07-31 18:29:13 [scrapy.utils.log] INFO: Versions: lxml 4.6.3.0, libxml2 2.9.10, cssselect 1.1.0, parsel 1.6.0, w3lib 1.22.0, Twisted 21.7.0, Python 3.7.11 (default, Jul 22 2021, 15:50:09) - [GCC 8.3.0], pyOpenSSL 20.0.1 (OpenSSL 1.1.1k 25 Mar 2021), cryptography 3.4.7, Platform linux-5.10.25-linuxkit-x86_64-with-debian-10.10
scrapycompositedemo_1 | 2021-07-31 18:29:13 [scrapy.utils.log] DEBUG: Using reactor: twisted.internet.asyncioreactor.AsyncioSelectorReactor
scrapycompositedemo_1 | 2021-07-31 18:29:13 [scrapy.utils.log] DEBUG: Using asyncio event loop: asyncio.unix_events.UnixSelectorEventLoop
scrapycompositedemo_1 | 2021-07-31 18:29:13 [scrapy.crawler] INFO: Overridden settings:
...
这里我们就可以看到,首先启动了 redis 服务,然后创建了 scrapycompositedemo 这个服务,接着运行了 Scrapy 爬虫项目并开始爬取对应的数据,在爬取过程中同时在控制台输出了对应的日志。
推送镜像
如果我们在本地测试镜像没有任何问题了,那接下来就可以把镜像推送到 Docker Hub 或其他的 Docker Registry Registry 服务上了,这里依然使用 docker-compose 所提供的命令即可:
docker-compose push
是的,也是非常简洁明了的命令,运行结果如下:
Pushing scrapycompositedemo (germey/scrapycompositedemo:latest)...
The push refers to repository [docker.io/germey/scrapycompositedemo]
836160d4c5c0: Pushed
f1408cfc4c45: Pushed
053b8bb0c2c1: Pushed
5fff6fa8a1637: Pushed
62499da5fab9: Mounted from library/python
afa3e488a0ee: Mounted from library/python
latest: digest: sha256:8d13cb16cb77cafa50a9c9665b1593f6997cc6a5c9bb95abd1d8458454393d2 size: 3052
执行完毕之后,我们指定的镜像就可以被推送到 Docker Hub 供其他主机下载运行了。