DEV Community

Flemming
Flemming

Posted on • Updated on

Development environment with Docker and Traefik

The Problem

Local development with docker is nothing new.
Run a local container export some ports and here we go.
But I ran into the problem of working with multiple projects at the same time of conflicting ports on my docker host. And it is hard to remember which project is running on which port. Local domains would be a nice solution.
I will walk you through my local development setup with docker and traefik to solve this problem.

Concept

We will install a reverse proxy on our local machine to add a domain to our projects. We will do this by using Traefik (https://traefik.io/traefik).
Traefik calls itself a cloud native application proxy.
It is ideal for using in cloud context like Kubernetes or docker. Traefik itself is also a simple docker container. And this will be the only container to expose a port to our docker host. The containers of the different projects and the traefik container will be in the same docker network. Traefik will forward the requests from the client to the corresponding container.

Concept skatch

Requirements

  • docker
  • docker-compose
  • your IDE of choice

Setup

Our first step will be to create a docker network.
We will call it "web". We are creating this network so that different docker-compose stacks can connect to each other.

docker network create web
Enter fullscreen mode Exit fullscreen mode

Now we are starting our traefik container.
We could do this by running a simple docker command, but in this case ware a using a small docker-compose file to configure our container.

version: '3'

networks:
  web:
    external: true

services:
  traefik:
    image: traefik:v2.3
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
    restart: always
    ports:
      - "80:80"
      - "8080:8080" # The Web UI (enabled by --api)
    networks:
      - web
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
Enter fullscreen mode Exit fullscreen mode

Save this file in a directory and start the container by typing

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

After the container started successfully we can access the traefik dashboard via http://localhost:8080.

Now we are starting a small web project. For example this is only a small website. I will only show the docker-compose.yml file in this post. You can find the complete folder structure and traefik setup here: https://github.com/flemssound/local-dev-docker-traefik

version: '3.3'

networks:
  web:
    external: true

services:
  application:
    image: nginx
    networks:
      - web
    # Here we define our settings for traefik how to proxy our service.
    labels:
      # This is enableing treafik to proxy this service
      - "traefik.enable=true"
      # Here we have to define the URL
      - "traefik.http.routers.myproject.rule=Host(`myproject.localhost`)"
      # Here we are defining wich entrypoint should be used by clients to access this service
      - "traefik.http.routers.myproject.entrypoints=web"
      # Here we define in wich network treafik can find this service
      - "traefik.docker.network=web"
      # This is the port that traefik should proxy
      - "traefik.http.services.myproject.loadbalancer.server.port=80"
    volumes:
      - ./html:/usr/share/nginx/html
    restart: always
Enter fullscreen mode Exit fullscreen mode

Now we can access our website via http://myproject.localhost.
Everything in the HTML folder is mounted to the public folder into the nginx container.
Instead of exposing the nginx port directly to our host we proxy it through traefik.
We can also see it in the traefik dashboard.
Traefik dashboard

To create another project copy the myproject folder, adjust the docker-compose.yml and start it up. Now we have a second project running, for example under mysecondproject.localhost also on port 80, and we don't have to worry about conflicting ports in our projects and can access them by their name.

References

Top comments (11)

Collapse
 
haofuxin profile image
Fuxin Hao

Thanks for your awesome article. But I still have a problem, what if some domain/port in third-parties SDKs are hard-coded. for example api.abc.com:1080 is hard-coded in a thrid-party SDK. how can I reroute it to myproject.localhost:80? the only thing I can think of is using something like iptables and editing /etc/hosts. Do u have some better ideas?

Collapse
 
flemming profile image
Flemming

I don't have a good solution for this. I think your way is the most simplest one.

Collapse
 
mrwormhole profile image
Talha Altınel • Edited

That's just very cool, i actually use nginx-reverse-proxy companion for my projects but i liked the observability dashboard on traefik a while ago but i didn't know about traefik pilot dashboard, there is not even a configuration file like nginx.conf, everything is in docker compose file i love it!

Collapse
 
flemming profile image
Flemming

Exactly the reason why I use I. No big configuration.

Collapse
 
a_regularjeff profile image
Jeff

Looks really amazing, I'm gonna start using it on my projects to see how it goes. Thanks for sharing!

Collapse
 
patricia_dugan profile image
patricia_dugan

Hi Flemming. I'm Patricia, Head of Community for Traefik. We'd like to invite you to become a Traefik Ambassador, as a contributor of code/content/community. We'll send goodies, invite you to the Traefik Ambassador Discord server, and also invite you to special Traefik Ambassador only events. Fill out the content sector here, and we'll get started! Thank you. info.traefik.io/traefik-ambassador...

Collapse
 
imthedeveloper profile image
ImTheDeveloper

I use traefik on most of my projects now and it's an absolute dream to work with. Highly recommend giving it a go before battling with nginx etc.

Collapse
 
flemming profile image
Flemming

Yes specially if you are hosting you services with docker. It is the perfect match. And you don't have to worry about Let's Encrypt certificats.

Collapse
 
michabbb_76 profile image
Michael Bladowski

how do you handle HTTPS in that scenario?

Collapse
 
flemming profile image
Flemming

I don't really need https for local development. But one possibility is to create a wildcard certificate for *.localhost and trust the CA by putting it in the local truststore.Then you have to extend traefik with the access point 443.

Collapse
 
michabbb_76 profile image
Michael Bladowski

i guess the best way (for me) is to find a simple free dns provider that is supported by letsencrpyt... so I don´t have to expose my ports or open and firewalls for the HTTP challenge....