From bdae9a67ce4b26bad63b90c34cf543db295390aa Mon Sep 17 00:00:00 2001
From: Googol Lee <i@googol.im>
Date: Tue, 23 Jul 2024 21:56:30 +0200
Subject: [PATCH] Add `Set up Docker development environment` in README.md
 (#997)

---
 Dockerfile       | 15 ++++++++++++--
 README.md        | 51 +++++++++++++++++++++++++++++++++++++++++++++---
 api/example.env  |  2 +-
 dev-compose.yaml | 38 ++++++++++++++++++++++++++++++++++++
 ui/package.json  |  2 +-
 5 files changed, 101 insertions(+), 7 deletions(-)
 create mode 100644 dev-compose.yaml

diff --git a/Dockerfile b/Dockerfile
index 125ce44..08f6429 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -60,8 +60,19 @@ RUN chmod +x /app/scripts/*.sh \
   # Build api source
   && go build -v -o photoview .
 
-### Copy api and ui to production environment ###
-FROM --platform=${BUILDPLATFORM:-linux/amd64} debian:bookworm-slim AS final
+### Build dev image for UI ###
+FROM ui AS dev-ui
+
+### Build dev image for API ###
+FROM api AS dev-api
+RUN source /app/scripts/set_compiler_env.sh \
+  && /app/scripts/install_runtime_dependencies.sh \
+  ## Install dev tools
+  && apt update \
+  && apt install -y reflex sqlite3
+
+### Build release image ###
+FROM --platform=${BUILDPLATFORM:-linux/amd64} debian:bookworm-slim AS release
 ARG TARGETPLATFORM
 
 # See for details: https://github.com/hadolint/hadolint/wiki/DL4006
diff --git a/README.md b/README.md
index adaa08d..8419ec8 100644
--- a/README.md
+++ b/README.md
@@ -169,9 +169,54 @@ It includes information on our code of conduct, the process for submitting pull
 
 Remember, every contribution counts. Let's make this project better together! 💪
 
-## Set up development environment
+## Set up Docker development environment
 
-### Developing dependencies
+Docker development environment is easy to set up. It only requires [Docker](https://docs.docker.com/engine/install/) and [Docker Compose Plugin](https://docs.docker.com/compose/install/) locally. All dependencies are installed in a container but not in the host.
+
+It also has some shortcomings. In macOS, Docker is running in a Linux VM. The fs notification doesn't work well in this case. You can't use `reflex` or `nodemon` to relaunch servers when code changes. The compiler runs pretty slow too.
+
+We recommend to use Docker development environment. If Docker environment doesn't work well, like on macOS, please use [local development environment](#set-up-local-development-environment).
+
+### Start API and UI server with Docker Compose
+
+It may take a long time to build dependencies when launching servers first time.
+
+```sh
+$ docker compose -f dev-compose.yaml build dev-ui dev-api # Build images for development
+$ docker compose -f dev-compose.yaml up dev-api dev-ui # Run API and UI servers
+```
+
+The graphql playground can now be accessed at [localhost:4001](http://localhost:4001). The site can now be accessed at [localhost:1234](http://localhost:1234). Both servers will be relaunched after the code is changed.
+
+### Start API server with Docker
+
+If you don't want to depend on Docker Compose but only Docker, you can launch server as below.
+
+It may take a long time to build dependencies when launching servers first time.
+
+```sh
+$ docker build --target dev-api -t photoview-api . # Build image for development
+$ cp api/example.env api/.env
+$ docker run --rm -it -v `pwd`:/app --network host photoview-api # Monitor source code and (re)launch API server
+```
+
+The graphql playground can now be accessed at [localhost:4001](http://localhost:4001).
+
+### Start UI server with Docker
+
+It may take a long time to build dependencies when launching servers first time.
+
+```sh
+$ docker build --target dev-ui -t photoview-ui .
+$ cp ./ui/example.env ./ui/.env
+$ docker run --rm -it -v `pwd`:/app --network host photoview-ui # Monitor source code and (re)launch UI server
+```
+
+The site can now be accessed at [localhost:1234](http://localhost:1234).
+
+## Set up local development environment
+
+### Install dependencies
 
 - API
   - Required packages:
@@ -270,7 +315,7 @@ If you want to recompile the server automatically when code changes:
 
 ```sh
 $ cd ./ui
-$ npm mon
+$ npm run mon
 ```
 
 The site can now be accessed at [localhost:1234](http://localhost:1234).
diff --git a/api/example.env b/api/example.env
index 62ecd58..fe6bf2f 100644
--- a/api/example.env
+++ b/api/example.env
@@ -12,7 +12,7 @@ PHOTOVIEW_SQLITE_PATH=photoview.db
 # See https://www.postgresql.org/docs/current/libpq-ssl.html for possible ssl modes
 # PHOTOVIEW_POSTGRES_URL=postgres://user:password@host:port/dbname?sslmode=(disable|allow|...)
 
-PHOTOVIEW_LISTEN_IP=localhost
+PHOTOVIEW_LISTEN_IP=0.0.0.0
 PHOTOVIEW_LISTEN_PORT=4001
 
 # The url from which the server can be accessed publicly
diff --git a/dev-compose.yaml b/dev-compose.yaml
new file mode 100644
index 0000000..3aa90aa
--- /dev/null
+++ b/dev-compose.yaml
@@ -0,0 +1,38 @@
+name: photoview
+
+services:
+  dev-ui:
+    image: photoview/photoview-ui
+    build:
+      context: .
+      dockerfile: Dockerfile
+      target: dev-ui
+    env_file: ui/example.env
+    volumes:
+    - .:/app:rw
+    ports:
+    - 1234:1234
+    command:
+    - /bin/bash
+    - -c
+    - |
+      npm ci
+      npm run mon
+
+  dev-api:
+    image: photoview/photoview-api
+    build:
+      context: .
+      dockerfile: Dockerfile
+      target: dev-api
+    env_file: api/example.env
+    volumes:
+    - .:/app:rw
+    ports:
+    - 4001:4001
+    command:
+    - /bin/bash
+    - -c
+    - |
+      source /app/scripts/set_compiler_env.sh 
+      reflex -g '*.go' -s -- go run .
diff --git a/ui/package.json b/ui/package.json
index 9d9bb54..2a4a21a 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -9,7 +9,7 @@
   "license": "GPL-3.0",
   "description": "UI app for Photoview",
   "scripts": {
-    "start": "vite",
+    "start": "vite --host=0.0.0.0",
     "mon": "nodemon",
     "build": "vite build",
     "lint": "eslint ./src --max-warnings 0 --config .eslintrc.js",
