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

Hom*_*lli 2 docker dockerfile docker-compose

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

我想将这个组件的子组件(管道)容器化,以便(如果需要),每个子组件或"服务/容器"(在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
Run Code Online (Sandbox Code Playgroud)

各种服务/组件/容器的定义如下:

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)
Run Code Online (Sandbox Code Playgroud)

这是我在最顶层的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
Run Code Online (Sandbox Code Playgroud)

如何编写docker-copose.yml文件以获得上述所需的功能?

lif*_*foo 6

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

默认

  • 您的服务将在docker-compose网络上提供,其名称与您正在使用的名称相同.因此,该db服务将成为db网络内的主机
  • 所有docker-compose服务都可以进行通信,因此您可以dbETL主机到达主机.如果需要,可以使用链接创建服务名称别名

Postgres的

只需要将数据库附加到以根据需要保留数据:

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
Run Code Online (Sandbox Code Playgroud)
  • ./pg-data 是主机操作系统上的本地目录(相对于您的docker-compose文件)(如果不存在,将创建它).
  • /var/lib/postgresql/data 是默认的postgres默认目录.
  • 您的本地目录./pg-data将映射到容器/var/lib/postgresql/data,因此postgres将在其中写入.

Dockerfile在你的db目录中看到了一个内容:如果你使用官方postgres图像,你不需要它.

ETL

要构建位于子目录中的服务,您可以使用自定义构建上下文.我将使用相对来从指定的目录构建服务映像Dockerfile.您可以使用dockerfile选项进一步自定义构建.

要将源链接到容器,只需使用另一个卷:

ETL:
  build:
    context: ./ETL
  volumes:
    - ./ETL:/YOUR/CONTAINER/APP_DIR
Run Code Online (Sandbox Code Playgroud)

这要求您的服务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"]
Run Code Online (Sandbox Code Playgroud)

在这种情况下,ETL服务的docker-compose卷将是:

  volumes:
    - ./ETL:/usr/src/app
Run Code Online (Sandbox Code Playgroud)

问题: - Should install mdal package when being built:这是什么意思?在哪里以及如何安装?

RESTAPI

Nginx将是你的gunicorn/flask应用程序的反向代理.所以你需要两个服务:

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

Nginx的

nginx:
  image: nginx
  ports:
    - "80:80"
  volume:
    - ./restapi/nginx.conf:/etc/nginx/conf.d/default.conf
Run Code Online (Sandbox Code Playgroud)

Nginx将成为您应用的主要接入点,因此端口80会在您的主机上公开:您可以通过以下方式访问您的应用http://localhost.

卷是一个"技巧",可以将配置文件添加到官方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;
  }
}
Run Code Online (Sandbox Code Playgroud)

gunicorn /烧瓶app

在这里你应该有一个Dockerfile使用类似的东西运行你的应用程序gunicorn -w 4 myapp:app(我从gunicorn网站上采取了基本的例子).

restapi:
  build:
    context: ./restapi
  expose:
    - "8000"
Run Code Online (Sandbox Code Playgroud)

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

mdal

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

建议阅读清单

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

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