我正在为更大的分布式系统开发一个组件(数据管道),它构成了应用程序的后端基础架构。
我想将这个组件的子组件(管道)容器化,以便(如果需要),每个子组件或“服务/容器”(在Docker术语中)可以在单独的物理机器上运行。
但是,某些子组件本身由其他服务组成。我是Docker和docker-compose的新手,并希望在汇总docker-compose文件以创建/配置系统方面提供一些帮助。
这是我的开发树结构,主要遵循建议的服务/容器之间的分区:
├── db
│ └── Dockerfile
├── docker-compose.yml
├── ETL
│ ├── archivers
│ ├── Dockerfile
│ └── feeds
│ ├── feeds
│ └── scrapy.cfg
├── mdal
│ ├── data
│ │ └── data_file
│ ├── LICENSE.txt
│ ├── MANIFEST.in
│ ├── README.rst
│ ├── sample
│ │ ├── __init__.py
│ │ └── package_data.dat
│ ├── setup.cfg
│ ├── setup.py
│ ├── tests
│ │ ├── __init__.py
│ │ └── test_simple.py
│ └── tox.ini
├── README
└── restapi
└── Dockerfile
各种服务/组件/容器的定义如下:
Service Description
======== ===================================================
db postgresql service, mounted on persistant volume
ETL ETL service (uses mdal to load/write from/to db)
mdal Python dbal package used by some components (uses db service)
restapi Nginx + gunicorn + flask app (uses mdal)
这是我在最顶端的docker-compose.yml文件中的尝试:
version: '3'
services:
# PostgreSQL service:
db:
container_name: postgres
restart: always
image: postgres:9.6.1
ports:
# We'll bind our host's port 5432 to postgres's port 5432, so we can use
# our database IDEs with it:
- 5432:5432
environment:
POSTGRES_PASSWORD: PG_PASS
# ETL service
ETL:
container_name: ETL
# Should install mdal package when being built
# Should link to my source files so changes are reflected
# Nginx + Gunicorn + Flask app exposing REST API
restapi:
container_name: restapi
# Should pull (versioned) Docker image for Nginx, Gunicorn, Flask
# Should link to my flask source files so changes are reflected
# Should install mdal package when being built
如何编写docker-copose.yml
文件以获得上述所需的功能?
答案 0 :(得分:5)
你使用基础结构是正确的,但如果你不熟悉Docker及其概念,这是一个非常复杂的配置。我将尝试逐步解释如何配置每项服务。
db
服务将是网络中的db
主机db
主机访问ETL
主机。如果需要,可以使用links 只需将数据库附加到volume即可保留数据:
db:
image: postgres:9.6.1
restart: always
volumes:
- ./pg-data:/var/lib/postgresql/data
ports:
# to attach external GUIs
- 5432:5432
environment:
- POSTGRES_PASSWORD: PG_PASS
./pg-data
是主机操作系统上的本地目录(相对于您的docker-compose文件)(如果不存在,将创建它)。/var/lib/postgresql/data
是默认的postgres默认目录。./pg-data
将映射到容器/var/lib/postgresql/data
,因此postgres将在其中写入。我在Dockerfile
目录中看到db
:如果您使用the official postgres image,则不需要它。
要构建位于子目录中的服务,您可以使用自定义build context。我将使用相对Dockerfile
从指定目录构建服务映像。您可以使用dockerfile选项进一步自定义构建。
要将您的来源链接到容器,只需使用另一个卷:
ETL:
build:
context: ./ETL
volumes:
- ./ETL:/YOUR/CONTAINER/APP_DIR
这要求您的服务Dockerfile
应如下所示:
FROM ubuntu
# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# Bundle app source
COPY . /usr/src/app
EXPOSE 80
CMD [ "python", "my-app.py"]
在这种情况下,ETL服务的docker-compose卷将是:
volumes:
- ./ETL:/usr/src/app
<强>问题强>:
- Should install mdal package when being built
:这是什么意思?在哪里以及如何安装?
Nginx将成为你的gunicorn / flask app的反向代理。所以你需要两个服务:
restapi
服务)nginx:
image: nginx
ports:
- "80:80"
volume:
- ./restapi/nginx.conf:/etc/nginx/conf.d/default.conf
Nginx将成为您应用的主要访问点,因此端口80会在您的主机上公开:您可以通过http://localhost
访问您的应用。
该卷是一个“技巧”,可以将配置文件添加到官方nginx映像而无需创建自定义nginx映像。默认情况下,nginx将加载.conf
内可用的任何/etc/nginx/conf.d
文件。我们在运行时使用自定义配置文件覆盖容器default.conf
。
这是一个示例配置文件,您应将其另存为./restapi/nginx.conf
:
server {
listen 80;
server_name ~^.*$;
location / {
proxy_pass http://restapi:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
在这里你应该有一个Dockerfile使用gunicorn -w 4 myapp:app
之类的东西运行你的应用程序(我从the gunicorn website得到了基本的例子)。
restapi:
build:
context: ./restapi
expose:
- "8000"
我们将gunicorn端口暴露给docker网络(你不能直接从你的主机到达它,但是nginx可以)。
谁在使用这个?它在哪里需要?
虽然docker和docker-compose文档非常详细,但我建议您阅读一些解释(太多)docker功能(和怪癖)的书籍: