Docker Compose

for

Developing Microservices

Can Kutlu Kınay
Software Engineer @ unu GmbH

cakuki

ckk.im

  • $> docker run --name db -p 27017:27017 -d mongo:3.6.0
  • $> docker run --name api -d \
  •                           --link db \
  •                           -p 3000:3000 \
  •                           api:latest npm start

 

 

 

 

  • $> for service in services/*; do
  •           docker run --name ${service}-service
  •                                --link db \
  •                                 --env CUSTOM_SETTING=? \
  •                                 --port ?? ...

Microservices

Enter
Docker
Compose

Defines whole stack

Single command

In isolated networks

How does it work?

Define images

Define stack

./api/Dockerfile

docker-compose.yml

Up!

FROM node:9.2

COPY package*.json ./
RUN npm install

COPY index.js

CMD ["npm", "start"]
version: '3'
services:
  web:
    image: nginx:1.13.7
    volumes:
    - ./web:/usr/share/nginx/html
    ports:
    - "8080:80"
  api:
    build: ./api/
    depends_on:
    - db
    ports:
    - "3000:3000"
  db:
    image: mongo:3.6.0
                
$> docker-compose up

Creating network "example_default"
Pulling db (mongo:3.6.0)...
3.6.0: Pulling from library/mongo
Building api
Step 1/5 : FROM node:9.2
9.2: Pulling from library/node
Step 2/5 : COPY package.json ./
Step 3/5 : RUN npm install
Step 4/5 : COPY index.js ./
Step 5/5 : CMD ["npm", "start"]
Successfully built
Successfully tagged example_api:latest
Creating example_db_1 ...
Creating example_db_1 ... done
Creating example_api_1 ...
Creating example_api_1 ... done
Creating example_web_1 ...
Creating example_web_1 ... done

api_1 | Example app listening on port 3000!

Basic Stack

version: '3'

services:
#---------------------------------
web:
  image: nginx:1.13.7
  volumes:
   - ./web:/usr/share/nginx/html
  ports:
   - "8080:80"
#---------------------------------
api:
  image: api:latest
  build: ./api/
  depends_on:
   - db
  ports:
   - "3000:3000"
#---------------------------------
db:
  image: mongo:3.6.0

foobar/docker-compose.yml

foobar_web_1
(nginx:1.13.7)

foobar_api_1
(api:latest)

foobar_db_1
(mongo:3.6.0)

foobar_network

web

api

What about more services?

services
├── cart
│   ├── Dockerfile
│   ├── index.js
│   └── package.json
├── checkout
│   ├── Dockerfile
│   ├── index.js
│   └── package.json
├── payment
│   ├── Dockerfile
│   ├── index.js
│   └── package.json
├── stock
│   ├── Dockerfile
│   ├── index.js
│   └── package.json
└── web
└── index.html
                      
version: '3.0'
services:
  cart-service:
    build: services/cart
    depends_on:
     - db
    ports:
     - 3000:3000/tcp
  checkout-service:
    build: services/checkout
    ...
  payment-service:
    build: services/payment
    ...
  stock-service:
    build: services/stock
    ...
  web:
    image: nginx:1.13.7
    ports:
     - 8080:80/tcp
    volumes:
     - ./services/web:/usr/share/nginx/html:rw
  db:
    image: mongo:3.6.0
                      

Even more services?

Growing
docker-compose.yml

version: '2.1'
services:
  web:
    extends:
      file: common-services.yml
      service: webapp
    environment:
     - DEBUG=1
    cpu_shares: 5

  important_web:
    extends: web
    cpu_shares: 10

Extending

$> docker-compose -f services/checkout/service.yml \
                            -f services/order/service.yml \
                            -f services/payment/service.yml \
                            ... \
                            up --detach

                          

Or multiple YAML files

Multiple YAML files

$> docker-compose -f services/checkout/service.yml \
                  -f services/order/service.yml \
                  -f services/payment/service.yml \
                  ... \
                  up --detach
                          

Template

for service in services; do;
cat >"stack/${service}.yml" <<EOF

version: '3'
services:
  ${service}-service:
    build: services/${service}
    depends_on:
    - db

EOF
done
                          
├── services
│   ├── cart
│   ├── checkout
│   ├── payment
│   ├── stock
│   └── web
├── stack
│   ├── cart.yml
│   ├── checkout.yml
│   ├── db.yml
│   ├── payment.yml
│   ├── stock.yml
│   └── web.yml
└── docker-compose.yml
                          

Wrapping it up (literally)

#!/bin/bash -e

CONFIG_FILES=(stack/*.yml)

docker-compose ${CONFIG_FILES[@]/#/-f} ${@}
                          
├── services
│   ├── cart
│   ├── checkout
│   ├── payment
│   ├── stock
│   └── web
├── stack
│   ├── cart.yml
│   ├── checkout.yml
│   ├── db.yml
│   ├── payment.yml
│   ├── stock.yml
│   └── web.yml
└── wrapper

./wrapper script

Replace all docker-compose commands

./wrapper up --build --scale api=2
                              ./wrapper down
                            
./wrapper up
#!/bin/bash -e

docker-compose -f stack/checkout.yml \
               -f stack/order.yml \
               ... \
               ${@}
                            

Thanks!

Questions?

Can Kutlu Kınay
Software Engineer @ unu GmbH

cakuki

ckk.im