Skip to content

AlMaVizca/dev-proxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Development proxy

Feel free to raise any issue or PR

Index

Motivation

It’s common for developers to work in more than one project at the same time and using different tools, which usually means different ports, if those ports implement the HTTP protocol, then there is no need to remember the ports number, and it could be accessed using DNS.

This repository is a showcase to simplify this access.

Requirements

  • Docker engine or podman
  • docker-compose
  • Use a local DNS

Configurations required

In order to resolve any subdomain, is possible to use dnsmasq.

Network manager and dnsmasq

address=/docker/172.17.0.1

and restart the service:

systemctl restart NetworkManager

Start the service

Only the first time it is required to create the network

make network

Then running make start it’s enough. As it’s the service will be always working, if you don’t want it to happen, please modify the restart configuration in docker-compose.yml

make start

Check that you can access to http://proxy.docker

Configure backend services

With that working adding the following configurations to a service in a docker-compose:

labels:
  traefik.enable: "true"
  traefik.http.routers.service-name.rule: "Host(`example.docker`)"
  traefik.http.services.service-name.loadbalancer.server.port: "<example-application-port>"
  traefik.webservice.service-name.entryPoints: http,ws
  traefik.http.routers.service-name.tls: "false"
  traefik.docker.network: lb
networks:
  lb:
    aliases:
      - ${SERVICE_NAME}.${DOMAIN}

Please be sure to modify service-name to avoid duplications, the domain ‘example.docker and also set the right port number on <example-application-port>

Then at the bottom of the docker-compose, you have to declare the access to the network:

networks:
  lb:
    name: lb
    external: true

With that in place and after you start the backend service, you will be able to access it through example.docker

Socket activation

The idea of socket activation is to not waste resources, so you start them only when you need it. While for the first attempt it might take a little bit to respond, I think it has a good compensation, it’s like a sustainability concept. To not use more than needed.

How does it works?

Nowadays it’s common that GNU/Linux operative systems use Systemd. I will leave it for you to learn it, if you are interested.

So we will have 3 parts, It could be done in 2 if the service that you are trying to run is able to receive a socket as a parameter, and altough it’s becoming more common, explainig a general solution for those services that don’t make the idea more complete.

On this example I will be using TCP/IP sockets, but you can choose file sockets as well.

  • The Socket service. It’s not a service per se, but a definition on where do we want systemd to be monitoring or waiting for incomming communication.
    [Unit]
    Description=Socket for EXAMPLE
    
    
    [Socket]
    
    ListenStream=GLOBAL_IP:GLOBAL_PORT
    Transparent=True
    
    [Install]
    WantedBy=sockets.target
        
  • The Service for the socket, or proxy service. Usually, if not defined on the socket definition, once a message is received, the socket will try to start a service with the same name as the socket definition, and pass the listening socket to the service. Since not all the services are prepared, as I mention before, here we will use a proxy service, that it’s able to direct the communication in the right path. So this will start the objective service, and deliver the messages to it.
    [Unit]
    Description=Intermediate proxy socket for EXAMPLE
    
    Requires=EXAMPLE-container.service
    After=EXAMPLE-container.service
    Requires=EXAMPLE.socket
    After=EXAMPLE.socket
    
    [Service]
    EnvironmentFile=SERVICE_PATH/.env
    ExecStart=/usr/lib/systemd/systemd-socket-proxyd --exit-idle-time="10m" ${SERVICE_IP}:${PORT_EXAMPLE}
    
    NonBlocking=true
        
  • The containerized service This is the actual service that we want to run.
    [Unit]
    Description=EXAMPLE container
    
    [Service]
    EnvironmentFile=SERVICE_PATH/.env
    # Use docker or podman, as you prefer it
    WorkingDirectory=SERVICE_PATH
    ExecStart=make start-service c=EXAMPLE
    ExecStop=make stop-service c=EXAMPLE
    
    [Install]
    WantedBy=multi-user.target
        

    To summarize the idea this sequence diagram might help:

Note: To make this work with TCP/IP, it’s required to use 2 different IP addresses, if you want to use the same port, or either use differnt port. I prefere different IPs because then I can have a proxy for docker and another for podman.

I just want it to work.

From theory to making it works requires an extra effort, and because I don’t like to waste time neither, you can just define your preferences on the .env file and run:

make install-sockets

About

Transparent http proxy to use DNS for development

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published