如何使用docker-compose对此应用程序进行容器化

时间:2017-09-22 15:00:01

标签: docker docker-compose dockerfile

我正在为更大的分布式系统开发一个组件(数据管道),它构成了应用程序的后端基础架构。

我想将这个组件的子组件(管道)容器化,以便(如果需要),每个子组件或“服务/容器”(在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文件以获得上述所需的功能?

1 个答案:

答案 0 :(得分:5)

你使用基础结构是正确的,但如果你不熟悉Docker及其概念,这是一个非常复杂的配置。我将尝试逐步解释如何配置每项服务。

默认值

  • 您的服务将在docker-compose网络上提供,其名称与您正在使用的名称相同。因此db服务将是网络中的db主机
  • 所有docker-compose服务都可以进行通信,因此您可以从db主机访问ETL主机。如果需要,可以使用links
  • 创建服务名称别名

的Postgres

只需将数据库附加到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,则不需要它。

ETL

要构建位于子目录中的服务,您可以使用自定义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:这是什么意思?在哪里以及如何安装?

RESTAPI

Nginx将成为你的gunicorn / flask app的反向代理。所以你需要两个服务:

  • 配置为反向代理的nginx服务
  • 运行gunicorn / flask应用程序(restapi服务)
  • 的服务

Nginx的

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;
  }
}

gunicorn / flask app

在这里你应该有一个Dockerfile使用gunicorn -w 4 myapp:app之类的东西运行你的应用程序(我从the gunicorn website得到了基本的例子)。

restapi:
  build:
    context: ./restapi
  expose:
    - "8000"

我们将gunicorn端口暴露给docker网络(你不能直接从你的主机到达它,但是nginx可以)。

mdal

谁在使用这个?它在哪里需要?

建议阅读清单

虽然dockerdocker-compose文档非常详细,但我建议您阅读一些解释(太多)docker功能(和怪癖)的书籍:

  • Docker in Action:Dockerfiles,图片,注册表,网络,卷。你需要知道的一切。必须从我的观点来看。
  • Docker in Practice:许多有趣且有用(甚至极端)的用例和解决方案。一本食谱。
  • The Docker book:通过实际例子学习。