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";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
output: "export",
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Reference in New Issue
Block a user