add Docker and CI/CD pipeline with ledo
Some checks failed
Docker - build image / 🏗️ Docker builder (latest from master) 🏗️ (push) Failing after 17s
Some checks failed
Docker - build image / 🏗️ Docker builder (latest from master) 🏗️ (push) Failing after 17s
Configure Next.js static export with nginx serving, Dockerfile (multi-stage build), docker-compose for prod/dev, Gitea Actions pipelines for build-on-push and tag-based releases using ledo tool. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
9
.dockerignore
Normal file
9
.dockerignore
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
node_modules
|
||||||
|
.next
|
||||||
|
.git
|
||||||
|
.gitea
|
||||||
|
.automancer
|
||||||
|
docker
|
||||||
|
*.md
|
||||||
|
.env*
|
||||||
|
.DS_Store
|
||||||
27
.gitea/workflows/docker-build.yml
Normal file
27
.gitea/workflows/docker-build.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
name: Docker - build image
|
||||||
|
run-name: ${{ gitea.actor }} builds image for project 🏗️
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "main"
|
||||||
|
jobs:
|
||||||
|
builder:
|
||||||
|
name: 🏗️ Docker builder (latest from master) 🏗️
|
||||||
|
runs-on: dind
|
||||||
|
steps:
|
||||||
|
- name: "[docker] registry login"
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: git.cynarski.pl
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
- name: "[code] repository checkout"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: "[ledo] Image build"
|
||||||
|
run: ledo image build
|
||||||
|
- name: "[ledo] Image push"
|
||||||
|
run: ledo image push
|
||||||
|
- name: "[docker] system prune"
|
||||||
|
run: docker system prune -af --volumes
|
||||||
35
.gitea/workflows/docker-tag.yml
Normal file
35
.gitea/workflows/docker-tag.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
name: Docker - build image
|
||||||
|
run-name: ${{ gitea.actor }} builds docker image for project 🏗️
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
jobs:
|
||||||
|
builder:
|
||||||
|
name: 🏗️ Docker builder release tag 🏗️
|
||||||
|
runs-on: dind
|
||||||
|
steps:
|
||||||
|
- name: "[docker] registry login"
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
registry: git.cynarski.pl
|
||||||
|
username: ${{ secrets.REGISTRY_USER }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
- name: "[code] repository checkout"
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
- name: checkout submodule
|
||||||
|
run: |
|
||||||
|
git submodule init
|
||||||
|
git submodule update
|
||||||
|
- name: "[ledo] Image build"
|
||||||
|
run: |
|
||||||
|
ledo image build
|
||||||
|
- name: "[ledo] Image retag and push"
|
||||||
|
run: |
|
||||||
|
export VERSION=$(echo $GITHUB_REF | cut -d '/' -f 3)
|
||||||
|
ledo image retag latest $VERSION
|
||||||
|
ledo image push $VERSION
|
||||||
|
- name: "[docker] system prune"
|
||||||
|
run: docker system prune -af --volumes
|
||||||
11
.ledo.yml
Normal file
11
.ledo.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
runtime: docker
|
||||||
|
docker:
|
||||||
|
registry: git.cynarski.pl
|
||||||
|
namespace: automancer
|
||||||
|
name: site
|
||||||
|
main_service: site
|
||||||
|
shell: /bin/bash
|
||||||
|
modes:
|
||||||
|
base: docker/docker-compose.yml
|
||||||
|
dev: docker/docker-compose.yml docker/docker-compose.dev.yml
|
||||||
|
test: docker/docker-compose.yml docker/docker-compose.test.yml
|
||||||
35
Dockerfile
Normal file
35
Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
|
############################
|
||||||
|
# 1) Dependencies
|
||||||
|
############################
|
||||||
|
FROM node:20-alpine AS deps
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
############################
|
||||||
|
# 2) Build stage
|
||||||
|
############################
|
||||||
|
FROM node:20-alpine AS build
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
############################
|
||||||
|
# 3) Production stage (nginx)
|
||||||
|
############################
|
||||||
|
FROM nginx:1.27-alpine AS production
|
||||||
|
|
||||||
|
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
COPY --from=build /app/out /usr/share/nginx/html
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
17
docker/docker-compose.dev.yml
Normal file
17
docker/docker-compose.dev.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
version: "3.7"
|
||||||
|
services:
|
||||||
|
site:
|
||||||
|
build:
|
||||||
|
context: ../
|
||||||
|
target: build
|
||||||
|
volumes:
|
||||||
|
- "../:/app"
|
||||||
|
- "/app/node_modules"
|
||||||
|
- "/app/.next"
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
command: npm run dev
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=development
|
||||||
|
networks:
|
||||||
|
- network-automancer-dev
|
||||||
11
docker/docker-compose.yml
Normal file
11
docker/docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
version: "3.7"
|
||||||
|
services:
|
||||||
|
site:
|
||||||
|
image: git.cynarski.pl/automancer/site:latest
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
networks:
|
||||||
|
- network-automancer-dev
|
||||||
|
|
||||||
|
networks:
|
||||||
|
network-automancer-dev: {}
|
||||||
39
docker/docker-entrypoint.sh
Executable file
39
docker/docker-entrypoint.sh
Executable file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
#
|
||||||
|
# H E L P E R F U N C T I O N S
|
||||||
|
#
|
||||||
|
##################################
|
||||||
|
declare -i term_width=80
|
||||||
|
|
||||||
|
|
||||||
|
h1() {
|
||||||
|
declare border padding text
|
||||||
|
border='\e[1;34m'"$(printf '=%.0s' $(seq 1 "$term_width"))"'\e[0m'
|
||||||
|
padding="$(printf ' %.0s' $(seq 1 $(((term_width - $(wc -m <<<"$*")) / 2))))"
|
||||||
|
text="\\e[1m$*\\e[0m"
|
||||||
|
echo -e "$border"
|
||||||
|
echo -e "${padding}${text}${padding}"
|
||||||
|
echo -e "$border"
|
||||||
|
}
|
||||||
|
|
||||||
|
h2() {
|
||||||
|
printf '\e[1;33m==>\e[37;1m %s\e[0m\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# M A I N F U N C T I O N S
|
||||||
|
#
|
||||||
|
#################################
|
||||||
|
|
||||||
|
h1 "Project init"
|
||||||
|
|
||||||
|
###
|
||||||
|
### Your code here
|
||||||
|
###
|
||||||
|
|
||||||
|
h1 "End of init"
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
29
docker/nginx.conf
Normal file
29
docker/nginx.conf
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
server {
|
||||||
|
listen 8080;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
add_header X-Content-Type-Options nosniff always;
|
||||||
|
add_header X-Frame-Options DENY always;
|
||||||
|
add_header Referrer-Policy strict-origin-when-cross-origin always;
|
||||||
|
|
||||||
|
# Static assets: cache aggressively
|
||||||
|
location ~* \.(?:css|js|mjs|map|png|jpg|jpeg|gif|svg|ico|webp|woff2|woff|ttf)$ {
|
||||||
|
expires 30d;
|
||||||
|
add_header Cache-Control "public, max-age=2592000, immutable";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# HTML: no cache
|
||||||
|
location ~* \.html$ {
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Next.js static export: try file, then file.html, then 404
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri.html $uri/ /404.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
docker/test-entrypoint.sh
Executable file
38
docker/test-entrypoint.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eo pipefail
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
#
|
||||||
|
# H E L P E R F U N C T I O N S
|
||||||
|
#
|
||||||
|
##################################
|
||||||
|
declare -i term_width=80
|
||||||
|
|
||||||
|
h1() {
|
||||||
|
declare border padding text
|
||||||
|
border='\e[1;34m'"$(printf '=%.0s' $(seq 1 "$term_width"))"'\e[0m'
|
||||||
|
padding="$(printf ' %.0s' $(seq 1 $(((term_width - $(wc -m <<<"$*")) / 2))))"
|
||||||
|
text="\\e[1m$*\\e[0m"
|
||||||
|
echo -e "$border"
|
||||||
|
echo -e "${padding}${text}${padding}"
|
||||||
|
echo -e "$border"
|
||||||
|
}
|
||||||
|
|
||||||
|
h2() {
|
||||||
|
printf '\e[1;33m==>\e[37;1m %s\e[0m\n' "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# M A I N F U N C T I O N S
|
||||||
|
#
|
||||||
|
#################################
|
||||||
|
|
||||||
|
h1 "Project test init"
|
||||||
|
|
||||||
|
###
|
||||||
|
### Your code here
|
||||||
|
###
|
||||||
|
|
||||||
|
h1 "End of test init"
|
||||||
|
|
||||||
|
exec "$@"
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import type { NextConfig } from "next";
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
/* config options here */
|
output: "export",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default nextConfig;
|
export default nextConfig;
|
||||||
|
|||||||
Reference in New Issue
Block a user