Published: Nov 30, 2023 by Isaac Johnson
We had so much fun with Docusaurus in that last post I figured it would be good idea to keep going. Last time we set up an initial Docusaurus instance locally, created some entries in blogs and docs then containerized the whole thing. I manually built and pushed to Harbor CR before working out some Kubernetes deployments and CronJobs.
The gaps, I see them include:
- We still have the ‘getting started’ landing page which looks pretty cheesy
- Building by hand is never a good pattern - let’s setup some form of Gitea/Github action.
- I would love to explore ways to post some candidate versions - like a pre-release.
The landing page
Let’s tackle this first.
We can change the images, theme colours and more
Most of the main configuration elements like Name, title and logo can be changed in the docusaurus.config.js file
builder@LuiGi17:~/Workspaces/docuSite/my-fb-website$ git diff docusaurus.config.js
diff --git a/docusaurus.config.js b/docusaurus.config.js
index 7b8d5b1..258566a 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -8,20 +8,20 @@ import {themes as prismThemes} from 'prism-react-renderer';
/** @type {import('@docusaurus/types').Config} */
const config = {
- title: 'My Site',
- tagline: 'Dinosaurs are cool',
+ title: 'Freshbrewed Documentation',
+ tagline: 'Docs from Cloudy McCloudface',
favicon: 'img/favicon.ico',
// Set the production url of your site here
- url: 'https://your-docusaurus-site.example.com',
+ url: 'https://docusaurus.freshbrewed.science',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
- organizationName: 'facebook', // Usually your GitHub org/user name.
- projectName: 'docusaurus', // Usually your repo name.
+ organizationName: 'idjohnson', // Usually your GitHub org/user name.
+ projectName: 'idjohnson', // Usually your repo name.
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
@@ -66,21 +66,21 @@ const config = {
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
navbar: {
- title: 'My Site',
+ title: 'Freshbrewed',
logo: {
- alt: 'My Site Logo',
- src: 'img/logo.svg',
+ alt: 'FB Logo',
+ src: 'img/builder.png',
},
items: [
{
type: 'docSidebar',
:...skipping...
diff --git a/docusaurus.config.js b/docusaurus.config.js
index 7b8d5b1..258566a 100644
--- a/docusaurus.config.js
+++ b/docusaurus.config.js
@@ -8,20 +8,20 @@ import {themes as prismThemes} from 'prism-react-renderer';
/** @type {import('@docusaurus/types').Config} */
const config = {
- title: 'My Site',
- tagline: 'Dinosaurs are cool',
+ title: 'Freshbrewed Documentation',
+ tagline: 'Docs from Cloudy McCloudface',
favicon: 'img/favicon.ico',
// Set the production url of your site here
- url: 'https://your-docusaurus-site.example.com',
+ url: 'https://docusaurus.freshbrewed.science',
// Set the /<baseUrl>/ pathname under which your site is served
// For GitHub pages deployment, it is often '/<projectName>/'
baseUrl: '/',
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
- organizationName: 'facebook', // Usually your GitHub org/user name.
- projectName: 'docusaurus', // Usually your repo name.
+ organizationName: 'idjohnson', // Usually your GitHub org/user name.
+ projectName: 'idjohnson', // Usually your repo name.
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
@@ -66,21 +66,21 @@ const config = {
// Replace with your project's social card
image: 'img/docusaurus-social-card.jpg',
navbar: {
- title: 'My Site',
+ title: 'Freshbrewed',
logo: {
- alt: 'My Site Logo',
- src: 'img/logo.svg',
+ alt: 'FB Logo',
+ src: 'img/builder.png',
},
items: [
{
type: 'docSidebar',
sidebarId: 'tutorialSidebar',
position: 'left',
- label: 'Tutorial',
+ label: 'Docs',
},
{to: '/blog', label: 'Blog', position: 'left'},
{
- href: 'https://github.com/facebook/docusaurus',
+ href: 'https://github.com/idjohnson/idjohnson',
label: 'GitHub',
position: 'right',
},
@@ -93,8 +93,8 @@ const config = {
title: 'Docs',
items: [
{
- label: 'Tutorial',
- to: '/docs/intro',
+ label: 'Playbooks',
+ to: '/docs/category/playbooks',
},
],
},
That updated the top banner
The three images and descriptions on the main page are configured in src/components/HomepageFeatures/index.js
. We don’t have to keep 3, but I did.
Because the FeatureList, as setup, wants an SVG
image, or scaled vector graphics, I used a free Adobe util page to convert MJ images to SVGs: https://new.express.adobe.com/tools/convert-to-svg
$ git diff src/components/HomepageFeatures/index.js
diff --git a/src/components/HomepageFeatures/index.js b/src/components/HomepageFeatures/index.js
index acc7621..3a40441 100644
--- a/src/components/HomepageFeatures/index.js
+++ b/src/components/HomepageFeatures/index.js
@@ -4,32 +4,29 @@ import styles from './styles.module.css';
const FeatureList = [
{
- title: 'Easy to Use',
- Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default,
+ title: 'Fun to Trash',
+ Svg: require('@site/static/img/mydinomean.svg').default,
description: (
<>
- Docusaurus was designed from the ground up to be easily installed and
- used to get your website up and running quickly.
+ While it is fun to let our Dinos tear about our hardware, sometimes it's better to use automation tools like AWX.
</>
),
},
{
- title: 'Focus on What Matters',
- Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default,
+ title: 'On Call is Great',
+ Svg: require('@site/static/img/mydinoheadphones.svg').default,
description: (
<>
- Docusaurus lets you focus on your docs, and we'll do the chores. Go
- ahead and move your docs into the <code>docs</code> directory.
+ Our Dinos love to chat on Zoom and Teams, but then they don't get anything done. Maybe it might be better to file a ticket
</>
),
},
{
- title: 'Powered by React',
- Svg: require('@site/static/img/undraw_docusaurus_react.svg').default,
+ title: 'Sharing Our Toys',
+ Svg: require('@site/static/img/mydinotoys.svg').default,
description: (
<>
- Extend or customize your website layout by reusing React. Docusaurus can
- be extended while reusing the same header and footer.
+ Dinos love to play and Dinos love to share. Go here to share your toys!
</>
),
},
which resulted in
The colour schemes are in defined in src/css/custom.css
$ git diff src/css/custom.css
diff --git a/src/css/custom.css b/src/css/custom.css
index 2bc6a4c..c9a62c0 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -6,25 +6,25 @@
/* You can override the default Infima variables here. */
:root {
- --ifm-color-primary: #2e8555;
- --ifm-color-primary-dark: #29784c;
- --ifm-color-primary-darker: #277148;
- --ifm-color-primary-darkest: #205d3b;
- --ifm-color-primary-light: #33925d;
- --ifm-color-primary-lighter: #359962;
- --ifm-color-primary-lightest: #3cad6e;
+ --ifm-color-primary: #852e2e;
+ --ifm-color-primary-dark: #782929;
+ --ifm-color-primary-darker: #712727;
+ --ifm-color-primary-darkest: #5d2020;
+ --ifm-color-primary-light: #923333;
+ --ifm-color-primary-lighter: #993535;
+ --ifm-color-primary-lightest: #ad3c3c;
--ifm-code-font-size: 95%;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
}
/* For readability concerns, you should choose a lighter palette in dark mode. */
[data-theme='dark'] {
- --ifm-color-primary: #25c2a0;
- --ifm-color-primary-dark: #21af90;
- --ifm-color-primary-darker: #1fa588;
- --ifm-color-primary-darkest: #1a8870;
- --ifm-color-primary-light: #29d5b0;
- --ifm-color-primary-lighter: #32d8b4;
- --ifm-color-primary-lightest: #4fddbf;
+ --ifm-color-primary: #c22525;
+ --ifm-color-primary-dark: #af2121;
+ --ifm-color-primary-darker: #a51f1f;
+ --ifm-color-primary-darkest: #881a1a;
+ --ifm-color-primary-light: #d52929;
+ --ifm-color-primary-lighter: #d83232;
+ --ifm-color-primary-lightest: #dd4f4f;
--docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
}
And the middle link is configured in the main ‘index.js’ page
$ git diff src/pages/index.js
diff --git a/src/pages/index.js b/src/pages/index.js
index a8c61f2..ff4c1cc 100644
--- a/src/pages/index.js
+++ b/src/pages/index.js
@@ -19,8 +19,8 @@ function HomepageHeader() {
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
- to="/docs/intro">
- Docusaurus Tutorial - 5min ⏱️
+ to="/docs/category/playbooks">
+ (⊙_☉) Read The _Fun_ Manaual 🤷🏽
</Link>
</div>
</div>
@@ -32,7 +32,7 @@ export default function Home() {
const {siteConfig} = useDocusaurusContext();
return (
<Layout
- title={`Hello from ${siteConfig.title}`}
+ title={`Greetings from ${siteConfig.title}`}
description="Description will go into a meta tag in <head />">
<HomepageHeader />
<main>
I’ll make an MR to come back to later
CICD
Now that it looks a bit nicer, let’s sort out our CICD
I’ll make a dir to hold the workflows
builder@LuiGi17:~/Workspaces/docuSite/my-fb-website$ code .
builder@LuiGi17:~/Workspaces/docuSite/my-fb-website$ mkdir -p .gitea/workflows
I’ll want to enable Repo Actions
While I don’t expect them to work, I first added the actions to main
name: CICD
run-name: $ building docusaurus
on: [push]
jobs:
BuildAndPush:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: dockerBuild
run: |
docker build --target development -t docusaurus:dev099 .
- name: dockerTag
run: |
docker tag docs:dev099 harbor.freshbrewed.science/freshbrewedprivate/docusaurus:dev099
- name: dockerTag
run: |
docker push harbor.freshbrewed.science/freshbrewedprivate/docusaurus:dev099
If we wish to test a build without adding more changes, we can always push an empty commit
builder@LuiGi17:~/Workspaces/docuSite/my-fb-website$ git commit --allow-empty -m "test"
[main 2de9208] test
builder@LuiGi17:~/Workspaces/docuSite/my-fb-website$ git push
Enumerating objects: 1, done.
Counting objects: 100% (1/1), done.
Writing objects: 100% (1/1), 184 bytes | 184.00 KiB/s, done.
Total 1 (delta 0), reused 0 (delta 0), pack-reused 0
remote: . Processing 1 references
remote: Processed 1 references in total
To https://gitea.freshbrewed.science/builder/MyFbWebsite.git
34f1e6d..2de9208 main -> main
This triggered the Gitea action
One of my challenges as I attempted to debug is that my particular containerized Gitea agent seems to not be able to access the docker socket. This means it’s not running in priveldged mode.
I have the option to try to enable that, or mount to the local filesystem (for docker.sock). I could pivot and add a Gitea agent on a physical host or VM with docker, or I could switch to Kaniko which doesn’t require access to docker.sock.
Kaniko is far more successful:
name: CICD
run-name: $ building docusaurus
on: [push]
jobs:
BuildAndPush:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: apt
run: |
# if running as non-root, add sudo
apt update
apt install -y apt-utils
- name: Kaniko build
uses: aevea/action-kaniko@master
with:
registry: harbor.freshbrewed.science
image: freshbrewedprivate/docusaurus
username: kaniko
password: $
cache: true
cache_registry: node:lts
To get it to build with Kaniko, I did need to comment out the user / group usage. I cannot explain it, but it refused to add users but would also claim the users did not exist
## Base ########################################################################
# Use a larger node image to do the build for native deps (e.g., gcc, python)
FROM node:lts as base
ENV GROUP_ID=1000 \
USER_ID=1000
# Reduce npm log spam and colour during install within Docker
ENV NPM_CONFIG_LOGLEVEL=warn
ENV NPM_CONFIG_COLOR=false
#USER root
#RUN addgroup --gid $GROUP_ID node
#RUN adduser --shell /bin/bash --uid $USER_ID --gid $GROUP_ID node
# We'll run the app as the `node` user, so put it in their home directory
WORKDIR /home/node/app
# Copy the source code over
COPY --chown=node:node . /home/node/app/
## Development #################################################################
# Define a development target that installs devDeps and runs in dev mode
FROM base as development
WORKDIR /home/node/app
# Install (not ci) with dependencies, and for Linux vs. Linux Musl (which we use for -alpine)
RUN npm install
# Switch to the node user vs. root
#RUN chown -R node:node /home/node/
#USER node
# Expose port 3000
EXPOSE 3000
# Start the app in debug mode so we can attach the debugger
CMD ["npm", "start"]
## Production ##################################################################
# Also define a production target which doesn't use devDeps
#FROM base as production
#WORKDIR /home/node/app
#COPY --from=development /home/node/app/node_modules /home/node/app/node_modules
# Build the Docusaurus app
#RUN npm run build
## Deploy ######################################################################
# Use a stable nginx image
#FROM nginx:stable-alpine as deploy
#WORKDIR /home/node/app
# Copy what we've installed/built from production
#COPY --from=production /home/node/app/build /usr/share/nginx/html/
This then built
I then uncommented those blocks
## Base ########################################################################
# Use a larger node image to do the build for native deps (e.g., gcc, python)
FROM node:lts as base
ENV GROUP_ID=1000 \
USER_ID=1000
# Reduce npm log spam and colour during install within Docker
ENV NPM_CONFIG_LOGLEVEL=warn
ENV NPM_CONFIG_COLOR=false
#USER root
#RUN addgroup --gid $GROUP_ID node
#RUN adduser --shell /bin/bash --uid $USER_ID --gid $GROUP_ID node
# We'll run the app as the `node` user, so put it in their home directory
WORKDIR /home/node/app
# Copy the source code over
COPY --chown=node:node . /home/node/app/
## Development #################################################################
# Define a development target that installs devDeps and runs in dev mode
FROM base as development
WORKDIR /home/node/app
# Install (not ci) with dependencies, and for Linux vs. Linux Musl (which we use for -alpine)
RUN npm install
# Switch to the node user vs. root
#RUN chown -R node:node /home/node/
#USER node
# Expose port 3000
EXPOSE 3000
# Start the app in debug mode so we can attach the debugger
CMD ["npm", "start"]
## Production ##################################################################
# Also define a production target which doesn't use devDeps
FROM base as production
WORKDIR /home/node/app
COPY --from=development /home/node/app/node_modules /home/node/app/node_modules
# Build the Docusaurus app
RUN npm run build
## Deploy ######################################################################
# Use a stable nginx image
FROM nginx:stable-alpine as deploy
WORKDIR /home/node/app
# Copy what we've installed/built from production
COPY --from=production /home/node/app/build /usr/share/nginx/html/
and added the target in the build file (CICD.yaml)
name: CICD
run-name: $ building docusaurus
on: [push]
jobs:
BuildAndPush:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: apt
run: |
# if running as non-root, add sudo
apt update
apt install -y apt-utils
- name: add Node Usr
run: |
export GROUP_ID=1111
export USER_ID=1111
addgroup --gid $GROUP_ID node || true
adduser -D --uid $USER_ID -G node node || true
- name: Kaniko build
uses: aevea/action-kaniko@master
with:
registry: harbor.freshbrewed.science
image: freshbrewedprivate/docusaurus
username: kaniko
password: $
cache: true
cache_registry: node:lts
target: development
which built and pushed
I can double check Harbor and see that SHA has the ‘main’ tag attached (the branch)
I’ll now edit the deployment to try it
builder@LuiGi17:~/Workspaces/PublicResume$ kubectl get deployment docusaurus-deployment -o yaml | grep -i image:
- image: harbor.freshbrewed.science/freshbrewedprivate/docusaurus:dev03
builder@LuiGi17:~/Workspaces/PublicResume$ kubectl edit deployment docusaurus-deployment
deployment.apps/docusaurus-deployment edited
builder@LuiGi17:~/Workspaces/PublicResume$ kubectl get deployment docusaurus-deployment -o yaml | grep -i image:
- image: harbor.freshbrewed.science/freshbrewedprivate/docusaurus:main
I can then see it come up (after I restored a missing CM)
builder@LuiGi17:~/Workspaces/PublicResume$ kubectl get pods | grep doc
docusaurus-deployment-7b57b4fdcc-8plm8 1/1 Running 0 6m9s
docusaurus-deployment-677b66659b-j79rf 0/1 Terminating 0 3d10h
builder@LuiGi17:~/Workspaces/PublicResume$ kubectl get pods | grep doc
docusaurus-deployment-7b57b4fdcc-8plm8 1/1 Running 0 6m22s
And just based on the UI we can see it was updated
Dual builds
I can then change the CICD file to pack in the build number and dev and prod
name: CICD
run-name: $ building docusaurus
on: [push]
jobs:
BuildAndPush:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: apt
run: |
# if running as non-root, add sudo
apt update
apt install -y apt-utils
- name: Debug
run: |
#!/bin/bash -x
export
- name: Kaniko build dev
uses: aevea/action-kaniko@master
with:
registry: harbor.freshbrewed.science
image: freshbrewedprivate/docusaurus
username: kaniko
password: $
cache: true
cache_registry: node:lts
target: development
tag: "dev$$"
- name: Kaniko build prod
uses: aevea/action-kaniko@master
with:
registry: harbor.freshbrewed.science
image: freshbrewedprivate/docusaurus
username: kaniko
password: $
cache: true
cache_registry: node:lts
target: production
tag: "prod$$"
- name: test
run: |
# Install Kubectl
curl -LO https://dl.k8s.io/release/v1.28.4/bin/linux/amd64/kubectl
chmod 755 ./kubectl
# Get Kubeconfig
echo $ | base64 --decode > /tmp/k8s
# Show Deployments
./kubectl get deployments --kubeconfig=/tmp/k8s
# Update Image
./kubectl set image deployment/docusaurus-deployment docusaurus-container=harbor.freshbrewed.science/freshbrewedprivate/docusaurus:dev$$
which we can see
And I can see them
What we can see is that after building, it deployed
$ kubectl get deployments docusaurus-deployment -o yaml | grep -i image:
- image: harbor.freshbrewed.science/freshbrewedprivate/docusaurus:devmain25
Let’s do an end-to-end demo:
Summary
We made several modifications to Docusaurus, including adjustments to its color scheme, links, and graphics. We then proceeded to modify the Docker containers and build them using a Gitea workflow before pushing them to Harbor CR. Finally, we demonstrated an end-to-end demo of the development and production container builds using Kaniko, followed by an automated deployment.