File size: 7,241 Bytes
050d2e1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
###################################################
# This Compose file provides the development environment for the todo app.
# 
# Seeing the final version of the application bundles the frontend with the
# backend, we are able to "simulate" that by using a proxy to route requests
# to the appropriate service. All requests to /api will be routed to the 
# backend while all other requests will be sent to the client service. While
# there is some overlap in the routing rules, the proxy determines the service
# based on the most specific rule.
#
# To support easier debugging and troubleshooting, phpMyAdmin is also included
# to provide a web interface to the MySQL database.
###################################################

###################################################
# Services
#
# The services define the individual components of our application stack.
# For each service, a separate container will be launched.
###################################################
services:

  ###################################################
  # Service: proxy
  #
  # This service is a reverse proxy that will route requests to the appropriate
  # service. Think of it like a HTTP router or a load balancer. It simply 
  # forwards requests and allows us to simulate the final version of the 
  # application where the frontend and backend are bundled together. We can 
  # also use it to route requests to phpMyAdmin, which won't be accessible at 
  # localhost, but at db.localhost.
  #
  # The image for this service comes directly from Docker Hub and is a Docker
  # Official Image. Since Traefik can be configured in a variety of ways, we
  # configure it here to watch the Docker events for new containers and to use
  # their labels for configuration. That's why the Docker socket is mounted.
  #
  # We also expose port 80 to connect to the proxy from the host machine.
  ###################################################
  proxy:
    image: traefik:v2.11
    command: --providers.docker
    ports:
      - 80:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

  ###################################################
  # Service: backend
  # 
  # This service is the Node.js server that provides the API for the app.
  # When the container starts, it will use the image that results
  # from building the Dockerfile, targeting the backend-dev stage.
  #
  # The Compose Watch configuration is used to automatically sync the code
  # from the host machine to the container. This allows the server to be
  # automatically reloaded when code changes are made.
  #
  # The environment variables configure the application to connect to the
  # database, which is also configured in this Compose file. We obviously
  # wouldn't hard-code these values in a production environment. But, in
  # dev, these values are fine.
  #
  # Finally, the labels are used to configure Traefik (the reverse proxy) with
  # the appropriate routing rules. In this case, all requests to localhost/api/*
  # will be forwarded to this service's port 3000. 
  ###################################################
  backend:
    build:
      context: ./
      target: backend-dev
    environment:
      MYSQL_HOST: mysql
      MYSQL_USER: root
      MYSQL_PASSWORD: secret
      MYSQL_DB: todos
    develop:
      watch:
        - path: ./backend/src
          action: sync
          target: /usr/local/app/src
        - path: ./backend/package.json
          action: rebuild
    labels:
      traefik.http.routers.backend.rule: Host(`localhost`) && PathPrefix(`/api`)
      traefik.http.services.backend.loadbalancer.server.port: 3000

  ###################################################
  # Service: client
  #
  # The client service is the React app that provides the frontend for the app.
  # When the container starts, it will use the image that results from building
  # the Dockerfile, targeting the dev stage.
  #
  # The Compose Watch configuration is used to automatically sync the code from
  # the host machine to the container. This allows the client to be automatically
  # reloaded when code changes are made.
  # 
  # The labels are used to configure Traefik (the reverse proxy) with the 
  # appropriate routing rules. In this case, all requests to localhost will be
  # forwarded to this service's port 5173.
  ###################################################
  client:
    build:
      context: ./
      target: client-dev
    develop:
      watch:
        - path: ./client/src
          action: sync
          target: /usr/local/app/src
        - path: ./client/package.json
          action: rebuild
    labels:
      traefik.http.routers.client.rule: Host(`localhost`)
      traefik.http.services.client.loadbalancer.server.port: 5173


  ###################################################
  # Service: mysql
  #
  # The MySQL service is used to provide the database for the application.
  # The image for this service comes directly from Docker Hub and is a Docker 
  # Official Image.
  
  # The data is persisted in a volume named todo-mysql-data. Using a volume 
  # allows us to take down the services without losing the data. When we start
  # the services again, the data will still be there (assuming we didn't delete
  # the volume, of course!).
  #
  # The environment variables configure the root password and the name of the
  # database to create. Since these are used only for local development, it's
  # ok to hard-code them here.
  ###################################################
  mysql:
    image: mysql:8.0
    volumes:
      - todo-mysql-data:/var/lib/mysql
    environment: 
      MYSQL_ROOT_PASSWORD: secret
      MYSQL_DATABASE: todos

  ###################################################
  # Service: phpmyadmin
  #
  # This service provides a web interface to the MySQL database. It's useful
  # for debugging and troubleshooting data, schemas, and more. The image for 
  # this service comes directly from Docker Hub and is a Docker Official Image.
  #
  # The environment variables configure the connection to the database and 
  # provide the default credentials, letting us immediately open the interface
  # without needing to log in.
  #
  # The labels are used to configure Traefik (the reverse proxy) with the
  # routing rules. In this case, all requests to db.localhost will be forwarded
  # to this service's port 80.
  ###################################################
  phpmyadmin:
    image: phpmyadmin
    environment:
      PMA_HOST: mysql
      PMA_USER: root
      PMA_PASSWORD: secret
    labels:
      traefik.http.routers.phpmyadmin.rule: Host(`db.localhost`)
      traefik.http.services.phpmyadmin.loadbalancer.server.port: 80

###################################################
# Volumes
#
# For this application stack, we only have one volume. It's used to persist the
# data for the MySQL service. We are only going to use the default values,
# hence the lack of any configuration for the volume.
###################################################
volumes:
  todo-mysql-data: