@@ -45,5 +45,6 @@ jobs:
|
||||
with:
|
||||
push: true
|
||||
tags: rmcampos/tasknote:${{ github.event.number }}
|
||||
build-args: BUILD=${{ github.event.number }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
auto_https off
|
||||
admin off
|
||||
}
|
||||
|
||||
:5000 {
|
||||
root * /app/dist
|
||||
|
||||
encode gzip
|
||||
|
||||
log {
|
||||
output stdout
|
||||
format console {
|
||||
time_format iso8601
|
||||
level_format color
|
||||
}
|
||||
level "{$LOG_LEVEL}"
|
||||
}
|
||||
|
||||
header {
|
||||
X-Frame-Options "SAMEORIGIN"
|
||||
X-XSS-Protection "1;mode=block"
|
||||
Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate"
|
||||
X-Content-Type-Options "nosniff"
|
||||
Strict-Transport-Security "max-age=31536000"
|
||||
Content-Security-Policy "
|
||||
base-uri 'self';
|
||||
connect-src 'self';
|
||||
default-src 'self';
|
||||
font-src https://cdn.jsdelivr.net/npm/ 'self';
|
||||
frame-src 'self';
|
||||
img-src 'self';
|
||||
manifest-src 'self';
|
||||
media-src 'self';
|
||||
object-src 'none';
|
||||
script-src 'unsafe-inline' 'report-sample' 'self';
|
||||
style-src https://cdn.jsdelivr.net/npm/ 'report-sample' 'self';
|
||||
worker-src 'none';
|
||||
"
|
||||
Referrer-Policy "same-origin"
|
||||
}
|
||||
|
||||
handle /env.js {
|
||||
header Content-Type "text/javascript"
|
||||
respond `window.config = {"BUILD":"{$BUILD}"};`
|
||||
}
|
||||
|
||||
file_server
|
||||
|
||||
handle_errors {
|
||||
@404 {
|
||||
expression {http.error.status_code} == 404
|
||||
}
|
||||
rewrite @404 /
|
||||
file_server
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Build static files
|
||||
# Node Bullseye has npm
|
||||
FROM node:20.17-bullseye-slim AS build
|
||||
ENV NODE_OPTIONS="--max-old-space-size=3072"
|
||||
|
||||
# Build
|
||||
WORKDIR /app
|
||||
COPY *.html *.json *.ts ./
|
||||
COPY ./src ./src
|
||||
COPY ./public ./public
|
||||
RUN npm ci --ignore-scripts --no-update-notifier --omit=dev && \
|
||||
npm run build && \
|
||||
rm -rf node_modules
|
||||
|
||||
# Deploy container
|
||||
# Caddy serves static files
|
||||
FROM caddy:2.8.4-alpine
|
||||
RUN apk add --no-cache ca-certificates curl
|
||||
|
||||
# Receive build number as argument, retain as environment variable
|
||||
ARG BUILD
|
||||
ENV BUILD=${BUILD}
|
||||
|
||||
# Copy files and run formatting
|
||||
COPY --from=build /app/dist/ /app/dist
|
||||
COPY Caddyfile /etc/caddy/Caddyfile
|
||||
RUN caddy fmt --overwrite /etc/caddy/Caddyfile
|
||||
|
||||
# User, port and healthcheck
|
||||
EXPOSE 5000
|
||||
HEALTHCHECK CMD curl -f http://localhost:5000
|
||||
USER 1001
|
||||
@@ -69,7 +69,7 @@ Contributions are what make the open-source community such an amazing place to l
|
||||
|
||||
## 📄 License
|
||||
|
||||
Distributed under the MIT License. See `LICENSE` for more information.
|
||||
Distributed under GPLv3 License. See `LICENSE` for more information.
|
||||
|
||||
## 📞 Contact
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
---
|
||||
|
||||
services:
|
||||
tasknote:
|
||||
container_name: tasknote
|
||||
profiles:
|
||||
- "dev"
|
||||
image: node:20.17-bullseye-slim
|
||||
ports:
|
||||
- "5000:5000"
|
||||
entrypoint: sh -c "npm i --no-update-notifier && npm start"
|
||||
user: root
|
||||
volumes:
|
||||
- "./:/app"
|
||||
working_dir: /app
|
||||
environment:
|
||||
LOG_LEVEL: debug
|
||||
healthcheck:
|
||||
test: timeout 10s bash -c 'true > /dev/tcp/127.0.0.1/3000'
|
||||
|
||||
caddy:
|
||||
container_name: caddy
|
||||
profiles:
|
||||
- "caddy"
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
BUILD: nightly
|
||||
ports:
|
||||
- "80:5000"
|
||||
volumes:
|
||||
- "./Caddyfile:/etc/caddy/Caddyfile"
|
||||
environment:
|
||||
LOG_LEVEL: debug
|
||||
healthcheck:
|
||||
test: timeout 10s bash -c 'true > /dev/tcp/127.0.0.1/3000'
|
||||
@@ -1,14 +1,20 @@
|
||||
import React from 'react';
|
||||
import style from './Footer.module.css';
|
||||
import { env } from '../env';
|
||||
|
||||
const Footer = () => (
|
||||
<footer className={style.footer}>
|
||||
<p>
|
||||
<span>React + TS Todo</span>
|
||||
{' '}
|
||||
@ 2022
|
||||
</p>
|
||||
</footer>
|
||||
);
|
||||
const Footer = () => {
|
||||
const build = env.BUILD;
|
||||
|
||||
return (
|
||||
<footer className={style.footer}>
|
||||
<p>
|
||||
<span>React + TS Todo</span>
|
||||
{' '}
|
||||
@ 2022
|
||||
{` Build: ${build}`}
|
||||
</p>
|
||||
</footer>
|
||||
);
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
|
||||
@@ -3,3 +3,22 @@
|
||||
- **TaskNote:** https://tasknote.local
|
||||
- **Docker Hub:** https://hub.docker.com/
|
||||
- **Time tracking:** https://track.toggl.com/timer
|
||||
|
||||
# Building locally
|
||||
|
||||
Build with Docker:
|
||||
|
||||
```sh
|
||||
docker build --build-arg BUILD=nightly -t tasknote:nightly .
|
||||
```
|
||||
|
||||
Run with Docker:
|
||||
```sh
|
||||
docker run -it --rm \
|
||||
--name tasknote \
|
||||
tasknote:nightly
|
||||
```
|
||||
Build and run with Docker Compose:
|
||||
```sh
|
||||
docker compose --profile caddy up --build
|
||||
```
|
||||
|
||||
+21
-1
@@ -5,7 +5,27 @@ import { fileURLToPath } from 'url';
|
||||
export default defineConfig(({ mode }: ConfigEnv) => {
|
||||
const config: UserConfig = {
|
||||
define: {} as any,
|
||||
plugins: [react()],
|
||||
plugins: [
|
||||
react(),
|
||||
{
|
||||
name: 'build-html',
|
||||
apply: 'build',
|
||||
transformIndexHtml: (html) => {
|
||||
return {
|
||||
html,
|
||||
tags: [
|
||||
{
|
||||
tag: 'script',
|
||||
attrs: {
|
||||
src: '/env.js'
|
||||
},
|
||||
injectTo: 'head'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
sourcemap: true
|
||||
|
||||
Reference in New Issue
Block a user