]> Untitled Git - lemmy.git/commitdiff
build: Minimize build time with multi-stage build, add Ingress and production versions
authorFelix Pojtinger <felix@pojtinger.com>
Sat, 27 Apr 2019 13:49:50 +0000 (15:49 +0200)
committerFelix Pojtinger <felix@pojtinger.com>
Sat, 27 Apr 2019 13:49:50 +0000 (15:49 +0200)
README.md
server/Dockerfile.dev
server/Dockerfile.prod [new file with mode: 0644]
server/stack.prod.yaml [new file with mode: 0644]
skaffold.yaml
ui/Dockerfile.dev
ui/Dockerfile.prod [new file with mode: 0644]
ui/stack.prod.yaml [new file with mode: 0644]

index 8e3db3857fd266a61719a2d86c46fab2c8196b47..8b7999a5477e79877843dfe2183fb0b72e6a39a6 100644 (file)
--- a/README.md
+++ b/README.md
 
 A link aggregator / reddit clone for the fediverse.
 
-[Lemmy Dev instance](https://dev.lemmy.ml) *for testing purposes only*
+[Lemmy Dev instance](https://dev.lemmy.ml) _for testing purposes only_
 
 This is a **very early beta version**, and a lot of features are currently broken or in active development, such as federation.
 
-|Front Page|Post|
-|-----------------------------------------------|----------------------------------------------- |
-|![main screen](https://i.imgur.com/y64BtXC.png)|![chat screen](https://i.imgur.com/vsOr87q.png) |
+| Front Page                                      | Post                                            |
+| ----------------------------------------------- | ----------------------------------------------- |
+| ![main screen](https://i.imgur.com/y64BtXC.png) | ![chat screen](https://i.imgur.com/vsOr87q.png) |
 
 ## Features
 
 - Open source, [AGPL License](/LICENSE).
 - Self hostable, easy to deploy.
-  - Comes with [docker](#docker).
+  - Comes with [Kubernetes](#kubernetes)
+  - Comes with [Docker](#docker).
 - Live-updating Comment threads.
 - Full vote scores `(+/-)` like old reddit.
 - Moderation abilities.
@@ -56,65 +57,66 @@ Made with [Rust](https://www.rust-lang.org), [Actix](https://actix.rs/), [Infern
 
 ## Usage
 
-### Production
+### Kubernetes
 
-#### Docker
+#### Requirements
 
-Make sure you have both docker and docker-compose installed.
-
-```
-git clone https://github.com/dessalines/lemmy
-cd lemmy
-./docker_update.sh # This pulls the newest version, builds and runs it
-```
-
-and goto http://localhost:8536
+- Local or remote Kubernetes cluster, i.e. [`minikube`](https://kubernetes.io/docs/tasks/tools/install-minikube/)
+- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
+- [`skaffold`](https://skaffold.dev/)
 
-<!-- #### Kubernetes (WIP)
+#### Production
 
-> TODO: Add production version with proper proxy setup and Ingress for WebSockets
+```bash
+# Deploy the Traefik Ingress
+kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-rbac.yaml
+kubectl apply -f https://raw.githubusercontent.com/containous/traefik/v1.7/examples/k8s/traefik-ds.yaml
+# Replace ${IP} with your Ingress' IP
+echo "${IP} dev.lemmy.local" >> /etc/hosts
+```
 
 ```bash
 skaffold run -p lemmy--prod
-# Now go to http://${IP}:30002
-``` -->
-
-### Development
-
-#### Kubernetes
-
-##### Requirements
+```
 
-- Local or remote Kubernetes cluster, i.e. [`minikube`](https://kubernetes.io/docs/tasks/tools/install-minikube/)
-- [`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/)
-- [`skaffold`](https://skaffold.dev/)
+Now go to http://dev.lemmy.local.
 
-##### Running
+#### Development
 
 ```bash
 skaffold dev -p lemmy--dev
 ```
 
-And goto http://localhost:4444 (automatically proxies to localhost, both if the cluster is local or remote).
+Now go to http://localhost:4444. It automatically proxies to localhost, both if the cluster is local or remote; it also hot-reloads the UI and automatically recompiles and restarts the server.
+
+### Docker
+
+Make sure you have both docker and docker-compose installed.
 
-It hot-reloads the UI and automatically recompiles the server.
+```
+git clone https://github.com/dessalines/lemmy
+cd lemmy
+./docker_update.sh # This pulls the newest version, builds and runs it
+```
+
+and goto http://localhost:8536
 
-#### Non-Kubernetes
+### Native
 
-##### Requirements
+#### Requirements
 
 - [Rust](https://www.rust-lang.org/)
 - [Yarn](https://yarnpkg.com/en/)
 - [Postgres](https://www.sqlite.org/index.html)
 
-##### Set up Postgres DB
+#### Set up Postgres DB
 
 ```
  psql -c "create user rrr with password 'rrr' superuser;" -U postgres
  psql -c 'create database rrr with owner rrr;' -U postgres
 ```
 
-##### Running
+#### Running
 
 ```
 git clone https://github.com/dessalines/lemmy
index c7951ce845299a08fef78d18e944e49b47581511..203dd74245086b8067338fc8f90cb2d78c35813b 100644 (file)
@@ -1,9 +1,7 @@
 # Setup env
-FROM rust:1.33
+FROM rust:1.33 AS build
 RUN USER=root cargo new --bin /opt/lemmy/server--dev
 WORKDIR /opt/lemmy/server--dev
-# Create empty directory where the frontend would normally be
-RUN mkdir -p /opt/lemmy/ui--dev/dist
 # Enable deps caching
 RUN mkdir -p src/bin
 RUN echo 'fn main() { println!("Dummy") }' >src/bin/main.rs
@@ -17,5 +15,14 @@ COPY src/ src/
 COPY migrations/ migrations/
 RUN rm target/release/deps/lemmy*
 RUN cargo build --release
+
+# Setup env (no Alpine because Rust requires glibc)
+FROM ubuntu:18.04
+RUN apt update
+RUN apt install postgresql-client -y
+# Create empty directory where the frontend would normally be
+RUN mkdir -p /opt/lemmy/ui--dev/dist
+# Add app
+COPY --from=build /opt/lemmy/server--dev/target/release/lemmy .
 # Run app
-CMD ["/opt/lemmy/server--dev/target/release/lemmy"]
+CMD ["./lemmy"]
diff --git a/server/Dockerfile.prod b/server/Dockerfile.prod
new file mode 100644 (file)
index 0000000..b375e47
--- /dev/null
@@ -0,0 +1,28 @@
+# Setup env
+FROM rust:1.33 AS build
+RUN USER=root cargo new --bin /opt/lemmy/server--prod
+WORKDIR /opt/lemmy/server--prod
+# Enable deps caching
+RUN mkdir -p src/bin
+RUN echo 'fn main() { println!("Dummy") }' >src/bin/main.rs
+# Install deps
+COPY Cargo.toml .
+COPY Cargo.lock .
+RUN cargo build --release
+RUN rm src/bin/main.rs
+# Add app
+COPY src/ src/
+COPY migrations/ migrations/
+RUN rm target/release/deps/lemmy*
+RUN cargo build --release
+
+# Setup env (no Alpine because Rust requires glibc)
+FROM ubuntu:18.04
+RUN apt update
+RUN apt install postgresql-client -y
+# Create empty directory where the frontend would normally be
+RUN mkdir -p /opt/lemmy/ui--prod/dist
+# Add app
+COPY --from=build /opt/lemmy/server--prod/target/release/lemmy .
+# Run app
+CMD ["./lemmy"]
diff --git a/server/stack.prod.yaml b/server/stack.prod.yaml
new file mode 100644 (file)
index 0000000..d221de1
--- /dev/null
@@ -0,0 +1,110 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: postgres
+data:
+  POSTGRES_PASSWORD: rrr
+  POSTGRES_USER: rrr
+  POSTGRES_DB: rrr
+  PGDATA: /var/lib/postgresql/data/pgdata
+  DATABASE_URL: postgres://rrr:rrr@postgres:5432/rrr
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: postgres
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 5Gi
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: postgres
+spec:
+  selector:
+    matchLabels:
+      app: postgres
+  template:
+    metadata:
+      labels:
+        app: postgres
+    spec:
+      containers:
+        - name: postgres
+          image: postgres:11.2-alpine
+          resources:
+            limits:
+              memory: 256Mi
+              cpu: 512m
+          ports:
+            - containerPort: 5432
+          envFrom:
+            - configMapRef:
+                name: postgres
+          volumeMounts:
+            - name: postgres
+              mountPath: /var/lib/postgresql/data
+      volumes:
+        - name: postgres
+          persistentVolumeClaim:
+            claimName: postgres
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: postgres
+spec:
+  selector:
+    app: postgres
+  ports:
+    - port: 5432
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: lemmy-server--prod
+data:
+  LEMMY_FRONT_END_DIR: /opt/lemmy/ui--prod/dist # not actually used here, polyfill for monolith
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: lemmy-server--prod
+spec:
+  selector:
+    matchLabels:
+      app: lemmy-server--prod
+  template:
+    metadata:
+      labels:
+        app: lemmy-server--prod
+    spec:
+      containers:
+        - name: lemmy-server--prod
+          image: registry.gitlab.com/pojntfx/lemmy/server.prod
+          envFrom:
+            - configMapRef:
+                name: postgres
+            - configMapRef:
+                name: lemmy-server--prod
+          resources:
+            limits:
+              memory: 512Mi
+              cpu: 512m
+          ports:
+            - containerPort: 8536
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: lemmy-server--prod
+spec:
+  selector:
+    app: lemmy-server--prod
+  ports:
+    - port: 8536
+      targetPort: 8536
index 9d1d3cd7d996f266f4e97e693be46bedf32e7cc6..9aeaa585921996a2722c32cca656aab1d306b5db 100644 (file)
@@ -19,5 +19,19 @@ profiles:
     deploy:
       kubectl:
         manifests:
-          - server/stack.dev.yaml
-          - ui/stack.dev.yaml
+          - "**/*.dev.yaml"
+  - name: lemmy--prod
+    build:
+      artifacts:
+        - image: registry.gitlab.com/pojntfx/lemmy/server.prod
+          context: server
+          docker:
+            dockerfile: Dockerfile.prod
+        - image: registry.gitlab.com/pojntfx/lemmy/ui.prod
+          context: ui
+          docker:
+            dockerfile: Dockerfile.prod
+    deploy:
+      kubectl:
+        manifests:
+          - "**/*.prod.yaml"
index 84ebbcadc742f85ed4cfb240a86518ba43e5c967..37f9e34c7b4d48cb9db297a05b8fbef47545aa03 100644 (file)
@@ -1,5 +1,5 @@
 # Setup env
-FROM node:10
+FROM node:10-alpine
 RUN mkdir -p /opt/lemmy/ui--dev
 WORKDIR /opt/lemmy/ui--dev
 # Install deps
@@ -9,4 +9,4 @@ RUN npm install
 # Add app
 COPY . .
 # Run app
-CMD npm start
+CMD ["npm", "start"]
diff --git a/ui/Dockerfile.prod b/ui/Dockerfile.prod
new file mode 100644 (file)
index 0000000..9c478e6
--- /dev/null
@@ -0,0 +1,22 @@
+# Setup env
+FROM node:10-alpine AS build
+RUN mkdir -p /opt/lemmy/ui--prod
+WORKDIR /opt/lemmy/ui--prod
+# Install deps
+COPY package.json .
+COPY yarn.lock .
+RUN npm install
+# Add app
+COPY . .
+# Build app
+RUN npm run build
+
+# Setup env
+FROM node:10-alpine
+RUN mkdir -p /opt/lemmy/ui--prod
+WORKDIR /opt/lemmy/ui--prod
+RUN npm install serve
+# Add app
+COPY --from=build /opt/lemmy/ui--prod/dist .
+# Run app
+CMD ["/opt/lemmy/ui--prod/node_modules/.bin/serve", "."]
diff --git a/ui/stack.prod.yaml b/ui/stack.prod.yaml
new file mode 100644 (file)
index 0000000..85ac6f6
--- /dev/null
@@ -0,0 +1,54 @@
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: lemmy-ui--prod
+spec:
+  selector:
+    matchLabels:
+      app: lemmy-ui--prod
+  template:
+    metadata:
+      labels:
+        app: lemmy-ui--prod
+    spec:
+      containers:
+        - name: lemmy-ui--prod
+          image: registry.gitlab.com/pojntfx/lemmy/ui.prod
+          resources:
+            limits:
+              memory: 1024Mi
+              cpu: 512m
+          ports:
+            - containerPort: 4444
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: lemmy-ui--prod
+spec:
+  selector:
+    app: lemmy-ui--prod
+  ports:
+    - port: 5000
+      targetPort: 5000
+---
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: lemmy-server--prod
+  annotations:
+    traefik.ingress.kubernetes.io/request-modifier: "ReplacePathRegex: ^/static/(.*) /$1"
+spec:
+  rules:
+    - host: dev.lemmy.local
+      http:
+        paths:
+          - path: /
+            backend:
+              serviceName: lemmy-ui--prod
+              servicePort: 5000
+          - path: /service/ws
+            backend:
+              serviceName: lemmy-server--prod
+              servicePort: 8536