Skip to content

Commit 8aa2248

Browse files
authored
Merge pull request #864 from DuendeSoftware/mb/staticredirects
Add Dockerfile to create container image
2 parents 4866557 + 255ea93 commit 8aa2248

7 files changed

Lines changed: 205 additions & 0 deletions

File tree

.dockerignore

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
**/.dockerignore
2+
**/.env
3+
**/.git
4+
**/.gitignore
5+
**/.project
6+
**/.settings
7+
**/.toolstarget
8+
**/.vs
9+
**/.vscode
10+
**/.idea
11+
**/*.*proj.user
12+
**/*.dbmdl
13+
**/*.jfm
14+
**/azds.yaml
15+
**/bin
16+
**/node_modules
17+
**/npm-debug.log
18+
**/obj
19+
**/secrets.dev.yaml
20+
**/values.dev.yaml
21+
22+
**/.devcontainer
23+
**/.fleet
24+
**/.husky
25+
**/.run
26+
**/.space
27+
**/dist
28+
docker-compose*.yml
29+
Dockerfile*
30+
LICENSE
31+
LICENSE-CODE
32+
README.md
33+
redirect.conf

Dockerfile

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
FROM node:22-alpine AS builder
2+
3+
EXPOSE 8080
4+
5+
WORKDIR /app
6+
COPY package.json package-lock.json ./
7+
RUN npm install --no-cache
8+
COPY . .
9+
RUN chmod +x build.sh
10+
11+
RUN ./build.sh
12+
13+
FROM nginx:stable-alpine AS final
14+
15+
ARG APPLICATION_VERSION
16+
COPY deployment/nginx.conf /etc/nginx/nginx.conf
17+
COPY deployment/default.conf /etc/nginx/conf.d/default.conf
18+
RUN sed -i "s|\$APPLICATION_VERSION|${APPLICATION_VERSION}|g" /etc/nginx/conf.d/default.conf
19+
COPY --from=builder --chown=nginx:nginx /app/root/redirect.conf /etc/nginx/extra/redirect.conf
20+
21+
RUN rm -rf /usr/share/nginx/html/*
22+
COPY --from=builder --chown=nginx:nginx /app/root/ /usr/share/nginx/html/
23+
RUN rm -rf /usr/share/nginx/html/redirect.conf
24+
25+
RUN mkdir -p /var/cache/nginx
26+
27+
RUN chown -R nginx:nginx /var/cache/nginx
28+
RUN touch /var/run/nginx.pid && \
29+
chown -R nginx:nginx /var/run/nginx.pid
30+
31+
USER nginx
32+
33+
WORKDIR /usr/share/nginx/html

astro.config.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import * as fs from "node:fs";
1616
// https://github.com/withastro/astro/issues/9782
1717
import { duendeOpenGraphImage } from "./src/plugins/duende-og-image.js";
1818
import removeMarkdownExtensions from "./src/plugins/remove-markdown-extensions.js";
19+
import staticRedirects from "./src/plugins/static-redirects.js";
1920

2021
// https://astro.build/config
2122
export default defineConfig({
@@ -218,6 +219,7 @@ export default defineConfig({
218219
redirectFrom({
219220
contentDir: "./src/content/docs",
220221
}),
222+
staticRedirects(),
221223
opengraphImages({
222224
options: {
223225
fonts: [

build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#!/bin/sh
12
set -e
23

34
npm install

deployment/default.conf

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
server {
2+
listen 8080;
3+
listen [::]:8080;
4+
server_name localhost;
5+
location / {
6+
root /usr/share/nginx/html;
7+
index index.html index.htm;
8+
add_header X-REVISION $APPLICATION_VERSION;
9+
}
10+
include /etc/nginx/extra/*.conf;
11+
12+
error_page 404 /404.html;
13+
location = /404.html {
14+
root /usr/share/nginx/html;
15+
}
16+
17+
error_page 500 502 503 504 /50x.html;
18+
location = /50x.html {
19+
root /usr/share/nginx/html;
20+
}
21+
}

deployment/nginx.conf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
user nginx;
2+
worker_processes auto;
3+
4+
error_log /var/log/nginx/error.log notice;
5+
pid /var/run/nginx.pid;
6+
7+
8+
events {
9+
worker_connections 1024;
10+
}
11+
12+
13+
http {
14+
include /etc/nginx/mime.types;
15+
default_type application/octet-stream;
16+
17+
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
18+
'$status $body_bytes_sent "$http_referer" '
19+
'"$http_user_agent" "$http_x_forwarded_for"';
20+
21+
access_log /var/log/nginx/access.log main;
22+
23+
sendfile on;
24+
#tcp_nopush on;
25+
26+
keepalive_timeout 65;
27+
28+
gzip on;
29+
30+
include /etc/nginx/conf.d/*.conf;
31+
}

src/plugins/static-redirects.ts

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import url from "node:url";
2+
import type { AstroConfig, AstroIntegrationLogger } from "astro";
3+
import path from "node:path";
4+
import fs from "node:fs/promises";
5+
6+
function createNginxRule(redirectFrom: string, redirectTo: string) {
7+
if (redirectFrom.endsWith("/")) {
8+
redirectFrom = redirectFrom.slice(0, -1);
9+
}
10+
11+
return (
12+
"rewrite ^" +
13+
redirectFrom +
14+
"(/?)$ $scheme://$http_host" +
15+
redirectTo +
16+
"/ permanent;\n"
17+
);
18+
}
19+
20+
let nginxRedirectRules = "";
21+
22+
export async function configurePlugin(hookOptions: any) {
23+
const buildOutput: string = hookOptions.buildOutput;
24+
const config: AstroConfig = hookOptions.config;
25+
const logger: AstroIntegrationLogger = hookOptions.logger;
26+
27+
if (buildOutput !== "static") {
28+
logger.warn(
29+
`Skip generating static redirects: not compatible with '${buildOutput}' builds, only 'static' is supported.`,
30+
);
31+
return;
32+
}
33+
34+
// Find redirects
35+
const redirects = config.redirects;
36+
if (!Object.keys(redirects).length) {
37+
logger.warn("Skip generating static redirects: no redirects found.");
38+
return;
39+
}
40+
41+
// Add redirects
42+
logger.info("Generating static redirects file...");
43+
Object.keys(redirects).forEach((from) => {
44+
const redirect = redirects[from];
45+
46+
if (typeof redirect === "string") {
47+
nginxRedirectRules += createNginxRule(from, redirect);
48+
} else {
49+
nginxRedirectRules += createNginxRule(from, redirect.destination);
50+
}
51+
});
52+
}
53+
54+
export async function writeToOutput(hookOptions: any) {
55+
const outDir: string = hookOptions.dir;
56+
const logger: AstroIntegrationLogger = hookOptions.logger;
57+
58+
if (!nginxRedirectRules || !nginxRedirectRules.length) {
59+
logger.warn(
60+
`Skip generating static redirects file: no redirects were generated.`,
61+
);
62+
return;
63+
}
64+
65+
// Write redirect.conf
66+
const configDestinationPath = path.join(
67+
url.fileURLToPath(outDir),
68+
"redirect.conf",
69+
);
70+
await fs.writeFile(configDestinationPath, nginxRedirectRules);
71+
logger.info(`Generated static redirects file: ${configDestinationPath}`);
72+
}
73+
74+
export default function staticRedirects() {
75+
return {
76+
name: "static-redirects",
77+
hooks: {
78+
"astro:config:done": async (hookOptions: any) =>
79+
await configurePlugin(hookOptions),
80+
"astro:build:done": async (hookOptions: any) =>
81+
await writeToOutput(hookOptions),
82+
},
83+
};
84+
}

0 commit comments

Comments
 (0)