Merge pull request #5344 from dokku/mkdocs-support
Generate docs via mkdocs
This commit is contained in:
@@ -7,6 +7,8 @@ build
|
||||
docs
|
||||
tests
|
||||
!build/package/*
|
||||
!docs/_build/entrypoint
|
||||
!docs/_build/requirements.txt
|
||||
!tests/dhparam.pem
|
||||
!contrib/bash-completion
|
||||
!contrib/docker
|
||||
|
||||
1
Makefile
1
Makefile
@@ -40,6 +40,7 @@ include common.mk
|
||||
|
||||
.PHONY: all apt-update install version copyfiles copyplugin man-db plugins dependencies docker-image-labeler lambda-builder netrc sshcommand procfile-util plugn docker aufs stack count vagrant-acl-add vagrant-dokku go-build
|
||||
|
||||
include docs.mk
|
||||
include tests.mk
|
||||
include package.mk
|
||||
include deb.mk
|
||||
|
||||
118
contrib/build-docs
Executable file
118
contrib/build-docs
Executable file
@@ -0,0 +1,118 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
readonly ROOT_DIR="$(cd "$(dirname "$(dirname "${BASH_SOURCE[0]}")")" && pwd)"
|
||||
|
||||
main() {
|
||||
pushd "$ROOT_DIR" >/dev/null || return 1
|
||||
rm -rf docs-main tmp/docs-source tmp/docs-build/docs # tmp/docs-build
|
||||
mkdir -p tmp/docs-build
|
||||
cp -r docs docs-main
|
||||
|
||||
echo "====> Processing version: latest"
|
||||
git clone -q https://github.com/dokku/dokku.git tmp/docs-source
|
||||
|
||||
rm -rf docs/assets
|
||||
mkdir -p docs/assets
|
||||
cp -r docs-main/assets/extra.css docs/assets/extra.css
|
||||
cp -r docs-main/assets/favicons docs/assets/favicons
|
||||
cp -r docs-main/assets/dokku-logo.svg docs/assets/dokku-logo.svg
|
||||
|
||||
rm -rf tmp/docs-build/assets
|
||||
cp -r docs-main/assets tmp/docs-build/assets
|
||||
cp docs-main/_build/app-nginx.conf.sigil tmp/docs-build/app-nginx.conf.sigil
|
||||
mkdir -p tmp/docs-build/nginx.conf.d
|
||||
touch tmp/docs-build/.static
|
||||
echo "[]" >tmp/docs-build/versions.json
|
||||
|
||||
sed -i.bak "s/outdated/outdated_hidden/g" docs/_overrides/main.html && rm docs/_overrides/main.html.bak
|
||||
echo "----> Generating docs"
|
||||
make docs-build
|
||||
rm -rf site/_build
|
||||
mv site tmp/docs-build/docs
|
||||
mv docs/home.html tmp/docs-build/index.html
|
||||
sed -i.bak "s/{{NAME}}~{{REF}}/docs/g" tmp/docs-build/index.html && rm tmp/docs-build/index.html.bak
|
||||
sed -i.bak "s/{{NAME}}/docs/g" tmp/docs-build/index.html && rm tmp/docs-build/index.html.bak
|
||||
sed -i.bak 's/="\/docs\/"/="\/"/g' tmp/docs-build/index.html && rm tmp/docs-build/index.html.bak
|
||||
|
||||
jq -C -r '.["max-versions"][]' docs-main/assets/versions.json | while read -r current_version; do
|
||||
major="$(echo "$current_version" | cut -d'.' -f1)"
|
||||
minor="$(echo "$current_version" | cut -d'.' -f2)"
|
||||
patch="$(echo "$current_version" | cut -d'.' -f3)"
|
||||
while true; do
|
||||
if [[ "$patch" -lt 0 ]]; then
|
||||
break
|
||||
fi
|
||||
version="${major}.${minor}.${patch}"
|
||||
echo "====> Processing version: ${major}.${minor}.${patch}"
|
||||
|
||||
if [[ "$major" -lt 1 ]]; then
|
||||
if [[ "$current_version" != "$version" ]]; then
|
||||
echo " Writing rewrite rule"
|
||||
echo "rewrite ^/docs~v$version/(.*)$ /docs~v$current_version/\$1 redirect;" >"tmp/docs-build/nginx.conf.d/$version.conf"
|
||||
echo " Removing old docs"
|
||||
rm -rf "tmp/docs-build/docs~v${version}"
|
||||
patch=$((patch - 1))
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
jq --arg title "v$version" --arg version "docs~v$version" '. += [{"title": $title, "version": $version, "aliases": []}]' tmp/docs-build/versions.json >tmp/docs-build/versions.json.bak
|
||||
mv tmp/docs-build/versions.json.bak tmp/docs-build/versions.json
|
||||
if [[ -d "tmp/docs-build/docs~v${version}" ]]; then
|
||||
echo " ! Docs exist, skipping regeneration"
|
||||
rm -rf "tmp/docs-build/docs~v${version}/assets/favicons"
|
||||
cp -r docs-main/assets/favicons "tmp/docs-build/docs~v${version}/assets/favicons"
|
||||
cp -r docs-main/assets/dokku-logo.svg "tmp/docs-build/docs~v${version}/assets/dokku-logo.svg"
|
||||
cp -r docs-main/assets/extra.css "tmp/docs-build/docs~v${version}/assets/extra.css"
|
||||
patch=$((patch - 1))
|
||||
continue
|
||||
fi
|
||||
|
||||
git -C tmp/docs-source checkout -q -- .
|
||||
git -C tmp/docs-source checkout -q "tags/v${version}" -b "v${version}-branch"
|
||||
rm -rf docs
|
||||
mv tmp/docs-source/docs docs
|
||||
|
||||
rm -rf docs/assets
|
||||
mkdir -p docs/assets
|
||||
cp -r docs-main/assets/favicons docs/assets/favicons
|
||||
cp -r docs-main/assets/dokku-logo.svg docs/assets/dokku-logo.svg
|
||||
cp -r docs-main/assets/extra.css docs/assets/extra.css
|
||||
|
||||
cp -r docs-main/_build docs/_build
|
||||
cp -r docs-main/_overrides docs/_overrides
|
||||
git checkout -q -- mkdocs.yml
|
||||
sed -i.bak "s/site_dir: site/site_dir: docs~v$version/g" mkdocs.yml && rm mkdocs.yml.bak
|
||||
if [[ ! -f docs/template.html ]]; then
|
||||
if [[ "$patch" -eq 0 ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
continue
|
||||
fi
|
||||
|
||||
echo "----> Generating docs"
|
||||
if ! make docs-build; then
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ -d "docs~v${version}" ]]; then
|
||||
rm -rf "docs~v${version}/_build"
|
||||
mv "docs~v${version}" "tmp/docs-build/docs~v${version}"
|
||||
fi
|
||||
|
||||
if [[ "$patch" -eq 0 ]]; then
|
||||
break
|
||||
fi
|
||||
patch=$((patch - 1))
|
||||
done
|
||||
done
|
||||
|
||||
python contrib/sort-mkdocs-versions
|
||||
rm -rf docs
|
||||
mv docs-main docs
|
||||
git checkout -- mkdocs.yml docs
|
||||
}
|
||||
|
||||
main "$@"
|
||||
38
contrib/sort-mkdocs-versions
Normal file
38
contrib/sort-mkdocs-versions
Normal file
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/env python
|
||||
import json
|
||||
|
||||
|
||||
def main():
|
||||
version_file = "tmp/docs-build/versions.json"
|
||||
data = []
|
||||
with open(version_file) as f:
|
||||
data = json.load(f)
|
||||
|
||||
versions = []
|
||||
for info in data:
|
||||
if info["title"] == "latest":
|
||||
continue
|
||||
versions.append(info["title"].removeprefix("v"))
|
||||
|
||||
versions.sort(key=lambda x: list(map(int, x.split('.'))), reverse=True)
|
||||
data = [
|
||||
{
|
||||
"aliases": ["latest"],
|
||||
"title": "latest",
|
||||
"version": "docs",
|
||||
}
|
||||
]
|
||||
|
||||
for version in versions:
|
||||
data.append({
|
||||
"aliases": [],
|
||||
"title": f"v{version}",
|
||||
"version": f"docs~v{version}",
|
||||
})
|
||||
|
||||
with open(version_file, "w") as f:
|
||||
json.dump(data, f, indent=4)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
343
contrib/write-mkdocs
Normal file
343
contrib/write-mkdocs
Normal file
@@ -0,0 +1,343 @@
|
||||
#!/usr/bin/env python
|
||||
from bs4 import BeautifulSoup
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
|
||||
def get_nav_from_selector(soup, selector, docs_dir):
|
||||
navigation = []
|
||||
header_name = ""
|
||||
for anchor in soup.select(selector):
|
||||
classes = anchor.get("class", [])
|
||||
if classes is None:
|
||||
continue
|
||||
|
||||
if "disabled" in classes:
|
||||
header_name = anchor.text
|
||||
navigation.append({header_name: []})
|
||||
|
||||
href = anchor.get("href", "")
|
||||
if href is None:
|
||||
continue
|
||||
|
||||
href = str(href)
|
||||
if href == "#":
|
||||
continue
|
||||
|
||||
url = href.replace("{{NAME}}", "")
|
||||
filename = url.replace("http://progrium.viewdocs.io/dokku/", "")
|
||||
filename = filename.replace("http://dokku.viewdocs.io/dokku/", "")
|
||||
filename = filename.strip("/") + ".md"
|
||||
filename = filename.removeprefix("dokku/")
|
||||
|
||||
ignore_errors_for = [
|
||||
"getting-started/installation.md",
|
||||
"getting-started/upgrading.md",
|
||||
]
|
||||
if not os.path.exists(docs_dir + "/" + filename):
|
||||
if filename not in ignore_errors_for:
|
||||
print("error fetching markdown file:", filename)
|
||||
continue
|
||||
|
||||
for nav in navigation:
|
||||
if header_name in nav:
|
||||
if filename == "getting-started/installation.md":
|
||||
child_dir = "getting-started/install/"
|
||||
children = os.listdir(docs_dir + "/" + child_dir)
|
||||
children = [child_dir + c for c in children]
|
||||
children.insert(
|
||||
0, "getting-started/advanced-installation.md")
|
||||
if os.path.exists(docs_dir + "/" + filename):
|
||||
children.insert(0, filename)
|
||||
else:
|
||||
children.insert(
|
||||
0, "getting-started/installation/index.md")
|
||||
nav[header_name].append({
|
||||
"Getting Started with Dokku": children,
|
||||
})
|
||||
continue
|
||||
elif filename == "getting-started/upgrading.md":
|
||||
child_dir = "appendices/"
|
||||
children = os.listdir(docs_dir + "/" + child_dir)
|
||||
|
||||
children.sort(key=lambda x: list(
|
||||
map(int, x.split("-")[0].split('.'))),
|
||||
reverse=True)
|
||||
children = [child_dir + c for c in children]
|
||||
if os.path.exists(docs_dir + "/" + filename):
|
||||
children.insert(0, filename)
|
||||
else:
|
||||
children.insert(
|
||||
0, "getting-started/upgrading/index.md")
|
||||
nav[header_name].append({
|
||||
"Upgrading": children,
|
||||
})
|
||||
continue
|
||||
else:
|
||||
nav[header_name].append(filename)
|
||||
return navigation
|
||||
|
||||
|
||||
def generate_nav(src, dest):
|
||||
navigation = []
|
||||
repo_dir = pathlib.Path(__file__).parent.parent.resolve()
|
||||
docs_dir = str(repo_dir) + "/docs"
|
||||
with open(docs_dir + "/template.html") as response:
|
||||
soup = BeautifulSoup(response, "html.parser")
|
||||
selectors = [
|
||||
".container .row .list-group a",
|
||||
".container-fluid .row .list-group a",
|
||||
]
|
||||
for selector in selectors:
|
||||
navigation = get_nav_from_selector(soup, selector, docs_dir)
|
||||
if len(navigation) > 0:
|
||||
break
|
||||
|
||||
if len(navigation) == 0:
|
||||
print("No navigation found")
|
||||
sys.exit(1)
|
||||
|
||||
with open(src) as f:
|
||||
data = yaml.unsafe_load(f)
|
||||
data["nav"] = [
|
||||
{"Docs": navigation},
|
||||
{"Pro": "https://pro.dokku.com/docs/getting-started/"},
|
||||
{"Blog": "https://dokku.github.io/"},
|
||||
{"Purchase Dokku Pro": "https://dokku.dpdcart.com/cart/add?product_id=217344&method_id=236878"},
|
||||
]
|
||||
|
||||
with open(dest, mode="wt", encoding="utf-8") as f:
|
||||
yaml.dump(data, f)
|
||||
|
||||
|
||||
def modify_content_noop(lines, _):
|
||||
modified = False
|
||||
updated_lines = []
|
||||
for line in lines:
|
||||
updated_lines.append(line)
|
||||
return updated_lines, modified
|
||||
|
||||
|
||||
def modify_content_links(lines, filename):
|
||||
filename = filename.replace("/usr/src/source/docs/", "")
|
||||
parts = filename.split("/")
|
||||
parts.pop()
|
||||
replacement = "](" + '/'.join([".." for _ in parts]) + "/"
|
||||
modified = False
|
||||
updated_lines = []
|
||||
for line in lines:
|
||||
if "](/docs/" in line:
|
||||
line = line.replace("](/docs/", replacement)
|
||||
modified = True
|
||||
|
||||
updated_lines.append(line)
|
||||
return updated_lines, modified
|
||||
|
||||
|
||||
def modify_content_stripspace(lines, _):
|
||||
modified = False
|
||||
updated_lines = []
|
||||
for line in lines:
|
||||
line = line.rstrip()
|
||||
updated_lines.append(line)
|
||||
return updated_lines, modified
|
||||
|
||||
|
||||
def modify_content_inject_newlines(lines, _):
|
||||
modified = False
|
||||
updated_lines = []
|
||||
for line in lines:
|
||||
updated_lines.append(line.rstrip() + "\n")
|
||||
return updated_lines, modified
|
||||
|
||||
|
||||
def is_info(line):
|
||||
return line.startswith("> ")
|
||||
|
||||
|
||||
def is_new(line):
|
||||
return line.startswith("> ") and "new as of" in line.lower()
|
||||
|
||||
|
||||
def is_note(line):
|
||||
return line.startswith("> Note:")
|
||||
|
||||
|
||||
def is_warning(line):
|
||||
return line.startswith("> Warning:")
|
||||
|
||||
|
||||
def modify_content_admonition(lines, _):
|
||||
modified = False
|
||||
updated_lines = []
|
||||
admonition_lines = []
|
||||
is_admonition = False
|
||||
for line in lines:
|
||||
if is_info(line) or is_new(line) or is_note(line) or is_warning(line):
|
||||
if is_new(line):
|
||||
line = line.replace("> ", "!!! tip \"New\"\n\n ")
|
||||
line = line.replace("New as of", "Introduced in")
|
||||
line = line.replace("new as of", "introduced in")
|
||||
if is_note(line):
|
||||
line = line.replace(
|
||||
"> Note: ", "!!! note \"Note\"\n\n ")
|
||||
elif is_warning(line):
|
||||
line = line.replace(
|
||||
"> Warning: ", "!!! warning \"Warning\"\n\n ")
|
||||
elif is_info(line):
|
||||
if not is_admonition:
|
||||
line = line.replace("> ", "!!! info \"Info\"\n\n ")
|
||||
elif line in [">", "> "]:
|
||||
line = ""
|
||||
else:
|
||||
line = " " + line.removeprefix("> ")
|
||||
|
||||
is_admonition = True
|
||||
admonition_lines.append(line)
|
||||
elif is_admonition and line in [">", "> "]:
|
||||
line = ""
|
||||
admonition_lines.append(line)
|
||||
elif is_admonition and line.startswith("> "):
|
||||
line = " " + line.removeprefix("> ")
|
||||
admonition_lines.append(line)
|
||||
elif line == "":
|
||||
is_admonition = False
|
||||
if len(admonition_lines) > 0:
|
||||
updated_lines.extend(admonition_lines)
|
||||
admonition_lines = []
|
||||
updated_lines.append("")
|
||||
else:
|
||||
updated_lines.append(line)
|
||||
return updated_lines, modified
|
||||
|
||||
|
||||
def is_shell_codeblock_start(line):
|
||||
return line == "```shell"
|
||||
|
||||
|
||||
def modify_content_terminal_example(lines, _):
|
||||
modified = False
|
||||
updated_lines = []
|
||||
command_block = []
|
||||
example_block = []
|
||||
in_command_block = False
|
||||
in_example_block = False
|
||||
previous_block = ""
|
||||
next_line_must_be = None
|
||||
for line in lines:
|
||||
if is_shell_codeblock_start(line):
|
||||
command_block.append(line)
|
||||
modified = True
|
||||
in_command_block = True
|
||||
continue
|
||||
elif in_command_block:
|
||||
command_block.append(line)
|
||||
if line == "```":
|
||||
in_command_block = False
|
||||
previous_block = "command_block"
|
||||
next_line_must_be = ""
|
||||
continue
|
||||
elif line == "```":
|
||||
if previous_block == "":
|
||||
updated_lines.append(line)
|
||||
continue
|
||||
elif previous_block == "command_block":
|
||||
example_block.append(line)
|
||||
|
||||
if in_example_block:
|
||||
previous_block = ""
|
||||
in_example_block = False
|
||||
updated_lines.append("=== \"Shell\"")
|
||||
updated_lines.append("")
|
||||
for command_line in command_block:
|
||||
updated_lines.append(f" {command_line}")
|
||||
command_block = []
|
||||
|
||||
updated_lines.append("")
|
||||
updated_lines.append("=== \"Output\"")
|
||||
updated_lines.append("")
|
||||
for example_line in example_block:
|
||||
updated_lines.append(f" {example_line}")
|
||||
example_block = []
|
||||
else:
|
||||
in_example_block = True
|
||||
continue
|
||||
elif previous_block == "command_block":
|
||||
if next_line_must_be is None:
|
||||
if in_example_block:
|
||||
example_block.append(line)
|
||||
else:
|
||||
updated_lines.extend(command_block)
|
||||
updated_lines.append("")
|
||||
updated_lines.append(line)
|
||||
command_block = []
|
||||
previous_block = ""
|
||||
continue
|
||||
elif next_line_must_be == "":
|
||||
if line == "":
|
||||
next_line_must_be = None
|
||||
continue
|
||||
|
||||
updated_lines.append(line)
|
||||
|
||||
if len(command_block) > 0:
|
||||
updated_lines.extend(command_block)
|
||||
|
||||
return updated_lines, modified
|
||||
|
||||
|
||||
def update_markdown(src):
|
||||
markdown_files = []
|
||||
allowed_extensions = [".md"]
|
||||
for subdir, _, files in os.walk(src):
|
||||
for file in files:
|
||||
ext = os.path.splitext(file)[-1].lower()
|
||||
file_path = os.path.join(subdir, file)
|
||||
if ext in allowed_extensions:
|
||||
markdown_files.append(file_path)
|
||||
|
||||
modifiers = [
|
||||
modify_content_noop,
|
||||
modify_content_links,
|
||||
modify_content_stripspace,
|
||||
modify_content_admonition,
|
||||
modify_content_terminal_example,
|
||||
modify_content_inject_newlines,
|
||||
]
|
||||
|
||||
for file in markdown_files:
|
||||
modified = False
|
||||
lines = []
|
||||
with open(file, 'r') as f:
|
||||
lines = f.readlines()
|
||||
for modifier in modifiers:
|
||||
lines, m = modifier(lines, file)
|
||||
if m:
|
||||
modified = True
|
||||
|
||||
if modified:
|
||||
with open(file, 'w') as fp:
|
||||
fp.writelines(lines)
|
||||
|
||||
|
||||
def main():
|
||||
print("----> Copying mkdocs.yml")
|
||||
print(" Generating navigation")
|
||||
generate_nav("/usr/src/source/mkdocs.yml", "/usr/src/app/mkdocs.yml")
|
||||
|
||||
print("----> Copying docs folder")
|
||||
update_markdown("/usr/src/source/docs",)
|
||||
|
||||
if os.path.exists("/usr/src/app/docs"):
|
||||
print(" Removing old docs folder")
|
||||
shutil.rmtree("/usr/src/app/docs")
|
||||
|
||||
print(" Performing copy")
|
||||
shutil.copytree("/usr/src/source/docs", "/usr/src/app/docs")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
19
docs.mk
Normal file
19
docs.mk
Normal file
@@ -0,0 +1,19 @@
|
||||
.PHONY: docs-build-image
|
||||
docs-build-image:
|
||||
docker build -f docs/_build/Dockerfile --progress plain -t app/mkdocs .
|
||||
|
||||
.PHONY: docs-build
|
||||
docs-build:
|
||||
@docker run --rm -p 3487:3487 -v "$(PWD):/usr/src/source" --name docs-serve app/mkdocs build
|
||||
|
||||
.PHONY: docs-serve
|
||||
docs-serve:
|
||||
docker run --rm -p 3487:3487 -v "$(PWD):/usr/src/source" --name docs-serve app/mkdocs serve
|
||||
|
||||
.PHONY: docs-deps
|
||||
docs-deps:
|
||||
@docker run --rm -p 3487:3487 -v "$(PWD):/usr/src/app" app/mkdocs deps
|
||||
|
||||
.PHONY: docs-enter
|
||||
docs-enter:
|
||||
docker exec -it docs-serve bash
|
||||
12
docs/_build/Dockerfile
vendored
Normal file
12
docs/_build/Dockerfile
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
FROM python:3.10-alpine
|
||||
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
COPY docs/_build/requirements.txt .
|
||||
|
||||
RUN apk add --no-cache bash yaml && \
|
||||
pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY docs/_build/entrypoint /bin/entrypoint
|
||||
|
||||
ENTRYPOINT [ "/bin/entrypoint" ]
|
||||
30
docs/_build/app-nginx.conf.sigil
vendored
Normal file
30
docs/_build/app-nginx.conf.sigil
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
worker_processes 1;
|
||||
error_log stderr;
|
||||
pid nginx.pid;
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
worker_connections 768;
|
||||
}
|
||||
|
||||
http {
|
||||
types_hash_max_size 2048;
|
||||
include mime.types;
|
||||
charset UTF-8;
|
||||
server {
|
||||
listen {{ $.PORT }};
|
||||
server_name _;
|
||||
root /app/www;
|
||||
index index.html;
|
||||
port_in_redirect off;
|
||||
|
||||
include /app/www/nginx.conf.d/*.conf;
|
||||
location ^~ /nginx.conf.d/ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
docs/_build/entrypoint
vendored
Executable file
39
docs/_build/entrypoint
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eo pipefail
|
||||
|
||||
write-mkdocs() {
|
||||
if [[ -f /usr/src/source/contrib/write-mkdocs ]]; then
|
||||
if ! python /usr/src/source/contrib/write-mkdocs; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
main() {
|
||||
declare CMD="$1" ARGS=("${@:2}")
|
||||
|
||||
if [[ "$CMD" == "build" ]]; then
|
||||
write-mkdocs
|
||||
echo "----> Executing mkdocs build"
|
||||
mkdocs build
|
||||
site_dir="$(grep site_dir mkdocs.yml | awk '{print $2}')"
|
||||
cp -r "/usr/src/app/${site_dir}" "/usr/src/source/${site_dir}"
|
||||
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [[ "$CMD" == "deps" ]]; then
|
||||
pip freeze
|
||||
return $?
|
||||
fi
|
||||
|
||||
if [[ "$CMD" == "serve" ]]; then
|
||||
write-mkdocs
|
||||
mkdocs serve -a 0.0.0.0:3487
|
||||
return $?
|
||||
fi
|
||||
|
||||
"$CMD" "${ARGS[@]}"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
23
docs/_build/requirements.txt
vendored
Normal file
23
docs/_build/requirements.txt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
beautifulsoup4==4.11.1
|
||||
click==8.1.3
|
||||
ghp-import==2.1.0
|
||||
importlib-metadata==4.12.0
|
||||
Jinja2==3.1.2
|
||||
Markdown==3.3.7
|
||||
MarkupSafe==2.1.1
|
||||
mergedeep==1.3.4
|
||||
mkdocs==1.3.1
|
||||
mkdocs-exclude==1.0.2
|
||||
mkdocs-material==8.4.2
|
||||
mkdocs-material-extensions==1.0.3
|
||||
packaging==21.3
|
||||
Pygments==2.13.0
|
||||
pymdown-extensions==9.5
|
||||
pyparsing==3.0.9
|
||||
python-dateutil==2.8.2
|
||||
PyYAML==6.0
|
||||
pyyaml_env_tag==0.1
|
||||
six==1.16.0
|
||||
soupsieve==2.3.2.post1
|
||||
watchdog==2.1.9
|
||||
zipp==3.8.1
|
||||
56
docs/_overrides/main.html
Normal file
56
docs/_overrides/main.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<!--
|
||||
Copyright (c) 2016-2022 Martin Donath <martin.donath@squidfunk.com>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
-->
|
||||
|
||||
{% extends "base.html" %}
|
||||
|
||||
<!-- Custom front matter -->
|
||||
{% block extrahead %}
|
||||
|
||||
<!-- Extra style sheets (can't be set in mkdocs.yml due to content hash) -->
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="{{ 'overrides/assets/stylesheets/main.css' | url }}"
|
||||
/>
|
||||
{% endblock %}
|
||||
|
||||
<!-- Announcement bar -->
|
||||
{% block announce %}
|
||||
<a href="https://twitter.com/dokku">
|
||||
For updates follow <strong>@dokku</strong> on
|
||||
<span class="twemoji twitter">
|
||||
{% include ".icons/fontawesome/brands/twitter.svg" %}
|
||||
</span>
|
||||
<strong>Twitter</strong>
|
||||
</a>
|
||||
{% endblock %}
|
||||
|
||||
<!-- Theme-related JavaScript -->
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
|
||||
<!-- Extra JavaScript (can't be set in mkdocs.yml due to content hash) -->
|
||||
<script src="{{ 'overrides/assets/javascripts/bundle.js' | url }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block outdated %}
|
||||
You're not viewing the latest version.
|
||||
<a href="{{ page.abs_url }}">
|
||||
<strong>Click here to go to latest.</strong>
|
||||
</a>
|
||||
{% endblock %}
|
||||
@@ -175,4 +175,4 @@ By default, Dokku will execute your buildpack app processes as the `herokuishuse
|
||||
|
||||
> NOTE: this user must exist in your herokuish image.
|
||||
|
||||
Additionally, the default `docker-local` scheduler that comes with Dokku will ensure your storage mounts are owned by either `herokuishuser` or the overridden value you have set in `DOKKU_APP_USER`. See the [docker-local scheduler documentation](/docs/advanced-usage/schedulers/docker-local.md#disabling-chown-of-persistent-storage) docs for more information.
|
||||
Additionally, the default `docker-local` scheduler that comes with Dokku will ensure your storage mounts are owned by either `herokuishuser` or the overridden value you have set in `DOKKU_APP_USER`. See the [docker-local scheduler documentation](/docs/deployment/schedulers/docker-local.md#disabling-chown-of-persistent-storage) docs for more information.
|
||||
|
||||
@@ -28,7 +28,7 @@ Valid resource options include:
|
||||
- `--network-egress`
|
||||
- `--nvidia-gpu`
|
||||
|
||||
See the [Supported Resource Management Properties](/docs/advanced-usage/schedulers/docker-local.md#supported-resource-management-properties) section of the docker local scheduler documentation for more information on how each resource limit maps to Docker.
|
||||
See the [Supported Resource Management Properties](/docs/deployment/schedulers/docker-local.md#supported-resource-management-properties) section of the docker local scheduler documentation for more information on how each resource limit maps to Docker.
|
||||
|
||||
Resource limits and reservations are applied only during the `run` and `deploy` phases of an application, and will not impact the `build` phase of an application.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ The [dokku-registry](https://github.com/dokku/dokku-registry) plugin is now buil
|
||||
- Builder plugins should call `post-release-builder` at the end of the build.
|
||||
- The `push` and `pull` command are not implemented. Users wishing to deploy a remote image should use `git:from-image`. Image pushing is not available at this time.
|
||||
- At this time, remote docker repositories are not automatically created for AWS, and users must create those repositories for their applications as necessary. This may be implemented in the future.
|
||||
- Docker images are only pushed when configured to do so. See the [registry management documentation](/docs/deployment/registry-management.md) for more details.
|
||||
- Docker images are only pushed when configured to do so. See the [registry management documentation](/docs/advanced-usage/registry-management.md) for more details.
|
||||
|
||||
Before upgrading, uninstall the registry plugin via `dokku plugin:uninstall registry`. Not doing so will cause issues with Dokku.
|
||||
|
||||
|
||||
5
docs/assets/extra.css
Normal file
5
docs/assets/extra.css
Normal file
@@ -0,0 +1,5 @@
|
||||
:root > * {
|
||||
--md-primary-fg-color: #2A8FBD;
|
||||
--md-primary-fg-color--light: #ECB7B7;
|
||||
--md-primary-fg-color--dark: #90030C;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
# Deploying to Dokku
|
||||
# Deploying an Application
|
||||
|
||||
> Note: This walkthrough uses the hostname `dokku.me` in commands. When deploying to your own server, you should substitute the domain `dokku.me` for the domain name or IP address associated with your server. Users of the Vagrant VM included with Dokku can use `dokku.me` which points to the IP of the VM.
|
||||
|
||||
@@ -105,7 +105,7 @@ Dokku supports deploying applications in a few ways:
|
||||
- [Heroku buildpacks](https://devcenter.heroku.com/articles/buildpacks) via [Herokuish](https://github.com/gliderlabs/herokuish#buildpacks): See the [herokuish buildpacks documentation](/docs/deployment/builders/herokuish-buildpacks.md) to learn about the different ways to specify a buildpack.
|
||||
- This is the default method used by Dokku.
|
||||
- [Dockerfile](https://docs.docker.com/reference/builder/): See the [dockerfile documentation](/docs/deployment/builders/dockerfiles.md) to learn about the different ways to configure Dockerfile-based deploys.
|
||||
- [Docker Image](https://docs.docker.com/get-started/overview/#docker-objects): See the [docker image documentation](/docs/deployment/methods/images.md) to learn about how to deploy a Docker Image.
|
||||
- [Docker Image](https://docs.docker.com/get-started/overview/#docker-objects): See the [docker image documentation](/docs/deployment/methods/git.md#initializing-an-app-repository-from-a-docker-image) to learn about how to deploy a Docker Image.
|
||||
|
||||
### Setting up SSL
|
||||
|
||||
@@ -242,7 +242,7 @@ See the [Dockerfile documentation](/docs/deployment/builders/dockerfiles.md) for
|
||||
|
||||
## Image tagging
|
||||
|
||||
See the [image tagging documentation](/docs/deployment/methods/images.md) for more information on how Docker images can be tagged and deployed for a given application.
|
||||
See the [image tagging documentation](/docs/deployment/methods/git.md#initializing-an-app-repository-from-a-docker-image) for more information on how Docker images can be tagged and deployed for a given application.
|
||||
|
||||
## Specifying a custom buildpack
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Cloud Native Buildpacks (Experimental)
|
||||
# Cloud Native Buildpacks
|
||||
|
||||
> New as of 0.22.0
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Herokuish Buildpack Deployment
|
||||
# Herokuish Buildpacks
|
||||
|
||||
> Subcommands new as of 0.15.0
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ The above command will show logs continually from the web process.
|
||||
|
||||
### Failed deploy logs
|
||||
|
||||
> Warning: The default [docker-local scheduler](/docs/advanced-usage/schedulers/docker-local.md) will "store" these until the next deploy or until the old containers are garbage collected - whichever runs first. If you require the logs beyond this point in time, please ship the logs to a centralized log server.
|
||||
> Warning: The default [docker-local scheduler](/docs/deployment/schedulers/docker-local.md) will "store" these until the next deploy or until the old containers are garbage collected - whichever runs first. If you require the logs beyond this point in time, please ship the logs to a centralized log server.
|
||||
|
||||
In some cases, it may be useful to retrieve the logs from a previously failed deploy.
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@ Dokku supports the following built-in schedulers:
|
||||
- `scheduler-docker-local`: Schedules apps against the local docker socket and runs containers directly on the Dokku host. See the [docker-local scheduler documentation](/docs/deployment/schedulers/docker-local.md) for more information on how this scheduler functions.
|
||||
- `scheduler-null`: Does nothing during the scheduler phase. See the [null scheduler documentation](/docs/deployment/schedulers/null.md) for more information on how this scheduler functions.
|
||||
|
||||
See the [alternate schedulers documentation](/docs/deployment/schedulers/alternate-schedulers.md) for more information on other scheduler plugins.
|
||||
|
||||
### Overriding the auto-selected scheduler
|
||||
|
||||
If desired, the scheduler can be specified via the `scheduler:set` command by speifying a value for `selected`. The selected scheduler will always be used.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Zero Downtime Deploys
|
||||
# Zero Downtime Deploy Checks
|
||||
|
||||
> New as of 0.5.0
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Upgrading
|
||||
|
||||
If your version of Dokku is pre 0.3.0 (check with `dokku version`), we recommend [a fresh install](/docs/getting-started/installation.md) on a new server.
|
||||
If your version of Dokku is pre 0.3.0 (check with `dokku version`), we recommend [a fresh install](/docs/getting-started/installation/index.md) on a new server.
|
||||
|
||||
## Security Updates
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
<main class="container px-4 px-lg-5">
|
||||
<div class="row">
|
||||
<div class="col-lg-7">
|
||||
<a class="badge-link" href="https://github.com/dokku/dokku/releases"><span class="badge py-2 d-flex fit-content"><div class="circle align-self-center me-2"></div>Latest release <span id="releaseVersion" class="ms-1">v0.27.1</span></span></a>
|
||||
<a class="badge-link" href="https://github.com/dokku/dokku/releases"><span class="badge py-2 d-flex fit-content"><div class="circle align-self-center me-2"></div>Latest release <span id="releaseVersion" class="ms-1">v0.28.1</span></span></a>
|
||||
<h1 class="text-white hero-heading mt-5">An open source PAAS alternative to Heroku.</h1>
|
||||
<h4 class="text-white mt-5">Dokku helps you build and manage the lifecycle of applications from building to scaling.</h4>
|
||||
<div class="d-flex mt-5">
|
||||
|
||||
@@ -65,7 +65,7 @@ If everything is working correctly, you should also be able to query for any oth
|
||||
|
||||
If they all return your IP address, you have set DNS up properly for dokku. You should also be able to `ssh root@myserver.example.tld` and access your server.
|
||||
|
||||
Proceed with the setup instructions in the [installation documentation](/docs/getting-started/installation.md)
|
||||
Proceed with the setup instructions in the [installation documentation](/docs/getting-started/installation/index.md)
|
||||
|
||||
### Using the root of your domain (node-js-app.example.tld)
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ Only a single `$IP:$PORT` combination can be routed to for a given app, and that
|
||||
|
||||
> New as of 0.20.0, Requires Docker 1.21+
|
||||
|
||||
Apps will default to being associated with the default `bridge` network or a network specified by the `initial-network` network property. Additionally, an app can be attached to `attachable` networks by changing the `attach-post-create` or `attach-post-deploy` network properties when using the [docker-local scheduler](/docs/advanced-usage/schedulers/docker-local.md). A change in these values will require an app deploy or rebuild.
|
||||
Apps will default to being associated with the default `bridge` network or a network specified by the `initial-network` network property. Additionally, an app can be attached to `attachable` networks by changing the `attach-post-create` or `attach-post-deploy` network properties when using the [docker-local scheduler](/docs/deployment/schedulers/docker-local.md). A change in these values will require an app deploy or rebuild.
|
||||
|
||||
```shell
|
||||
# associates the network after a container is created but before it is started
|
||||
|
||||
@@ -198,7 +198,6 @@
|
||||
<a href="/{{NAME}}/deployment/schedulers/kubernetes/" class="list-group-item">Kubernetes</a>
|
||||
<a href="/{{NAME}}/deployment/schedulers/nomad/" class="list-group-item">Nomad</a>
|
||||
<a href="/{{NAME}}/deployment/schedulers/null/" class="list-group-item">Null Scheduler</a>
|
||||
<a href="/{{NAME}}/deployment/schedulers/alternate-schedulers/" class="list-group-item">Alternate Schedulers</a>
|
||||
|
||||
<a href="#" class="list-group-item disabled">Development</a>
|
||||
|
||||
|
||||
91
mkdocs.yml
Normal file
91
mkdocs.yml
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
# yaml-language-server: $schema=https://squidfunk.github.io/mkdocs-material/schema.json
|
||||
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- attr_list
|
||||
- footnotes
|
||||
- md_in_html
|
||||
- pymdownx.details
|
||||
- pymdownx.emoji:
|
||||
emoji_generator: !!python/name:materialx.emoji.to_svg
|
||||
emoji_index: !!python/name:materialx.emoji.twemoji
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.snippets
|
||||
- pymdownx.superfences
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
- tables
|
||||
|
||||
repo_url: https://github.com/dokku/dokku
|
||||
|
||||
site_dir: site
|
||||
site_name: Dokku Documentation
|
||||
site_url: https://dokku.com/docs/
|
||||
|
||||
extra:
|
||||
social:
|
||||
- icon: fontawesome/brands/github
|
||||
link: https://github.com/dokku/dokku
|
||||
- icon: fontawesome/solid/bug
|
||||
link: https://github.com/dokku/dokku/issues
|
||||
- icon: fontawesome/brands/discord
|
||||
link: https://discord.gg/YQjANGMZvu
|
||||
- icon: fontawesome/brands/slack
|
||||
link: https://slack.dokku.com/
|
||||
- icon: fontawesome/solid/hashtag
|
||||
link: https://webchat.libera.chat/?channels=dokku
|
||||
- icon: fontawesome/brands/twitter
|
||||
link: https://twitter.com/dokku
|
||||
- icon: fontawesome/solid/comments
|
||||
link: https://github.com/dokku/dokku/discussions
|
||||
- icon: fontawesome/solid/cart-shopping
|
||||
link: https://dokku.dpdcart.com/cart/add?product_id=217344&method_id=236878
|
||||
version:
|
||||
provider: mike
|
||||
|
||||
theme:
|
||||
custom_dir: docs/_overrides
|
||||
favicon: assets/favicons/favicon-96x96.png
|
||||
features:
|
||||
- navigation.indexes
|
||||
- navigation.instant
|
||||
- navigation.sections
|
||||
- navigation.tabs
|
||||
- navigation.top
|
||||
- search.highlight
|
||||
homepage: https://dokku.com
|
||||
icon:
|
||||
admonition:
|
||||
tip: fontawesome/solid/wand-magic-sparkles
|
||||
logo: assets/dokku-logo.svg
|
||||
name: material
|
||||
palette:
|
||||
# Palette toggle for light mode
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: default
|
||||
toggle:
|
||||
icon: material/toggle-switch
|
||||
name: Switch to dark mode
|
||||
|
||||
# Palette toggle for dark mode
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: slate
|
||||
toggle:
|
||||
icon: material/toggle-switch-off-outline
|
||||
name: Switch to light mode
|
||||
|
||||
plugins:
|
||||
- search
|
||||
- exclude:
|
||||
glob:
|
||||
- _build/Dockerfile
|
||||
- _build/entrypoint
|
||||
- _build/requirements.txt
|
||||
- home.html
|
||||
- template.html
|
||||
|
||||
extra_css:
|
||||
- assets/extra.css
|
||||
Reference in New Issue
Block a user