Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Docker Compose: Mock external services

I have the following situation:

My application consists of a single web service that calls an external API (say, some SaaS service, ElasticSearch or so). For non-unit-testing purposes we want to control the external service and later also inject faults. The application and the "mocked" API are dockerized and now I want to use docker-compose to spin all containers up.

Because the application has several addresses hardcoded (e.g. the hostname of external services) I cannot change them and need to work around.

The service container makes a call to http://external-service.com/getsomestuff.

My idea was to use some features that are provided by docker to reroute all outgoing traffic to the external http://external-service.com/getsomestuff to the mock container without changing the URL.

My docker-compose.yaml looks like:

version: '2'
services:
  service:
    build: ./service
    container_name: my-service1
    ports:
      - "5000:5000"
    command: /bin/sh -c "python3 app.py"

  api:
    build: ./api-mock
    container_name: my-api-mock
    ports:
      - "5001:5000"
    command: /bin/sh -c "python3 app.py"

Finally, I have a driver that just does the following:

curl -XGET localhost:5000/
curl -XPUT localhost:5001/configure?delay=10
curl -XGET localhost:5000/

where the second curl just sets the delay in the mock to 10 seconds.

There are several options I have considered:

  • Using iptables-fu (would require modifying Dockerfiles to install it)
  • Using docker networks (this is really unclear to me)

Is there any simple option to achieve what I want?

Edit:

For clarity, here is the relevant part of the service code:

import requests

@app.route('/')
def do_stuff():
    r = requests.get('http://external-service.com/getsomestuff')
    return process_api_response(r.text())
like image 593
teekay Avatar asked Mar 22 '17 23:03

teekay


People also ask

What is the purpose of mock server?

Mock servers simulate an API by returning predefined data, enabling you to develop or test against an API before it's production-ready (or without using production data). In Postman, mock servers rely on examples saved in a collection to return mock data.


1 Answers

Docker runs an internal DNS server for user defined networks. Any unknown host lookups are forwarded to you normal DNS servers.

Version 2+ compose files will automatically create a network for compose to use so there's a number of ways to control the hostnames it resolves.

The simplest way is to name your container with the hostname:

version: "2"
services:
  external-service.com:
    image: busybox
    command: sleep 100
  ping:
    image: busybox
    command: ping external-service.com
    depends_on:
      - external-service.com

If you want to keep container names you can use links

version: "2"
services:
  api:
    image: busybox
    command: sleep 100
  ping:
    image: busybox
    links:
      - api:external-service.com
    command: ping external-service.com
    depends_on:
      - api

Or network aliases

version: "2"
services:
  api:
    image: busybox
    command: sleep 100
    networks:
      pingnet:
        aliases:
        - external-service.com
  ping:
    image: busybox
    command: ping external-service.com
    depends_on:
      - api
    networks:
      - pingnet
networks:
  pingnet:
like image 116
Matt Avatar answered Oct 03 '22 06:10

Matt