github:https://github.com/TryGhost/Ghost

docker [ghost]:https://hub.docker.com/_/ghost

docker [mysql]:https://hub.docker.com/_/mysql

1 mysql

1.1 数据文件映射

# 启动临时环境mysql8,并复制mysql8的数据文件到主机目录
docker run -dit --rm --name mysql8 -e MYSQL_ROOT_PASSWORD=root mysql:8  # 启动mysql8
docker ps -a # 查看mysql8对应的容器ID
mkdir -p /cz/docker/mysql # 创建目录
docker cp b9214b7b1a42:/var/lib/mysql /cz/docker/mysql/data # 复制容器的数据文件到主机目录下
docker stop mysql8 # 停止

1.2 启动

docker run -dit --rm --name mysql8 \
-v /cz/docker/mysql/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-p 3306:3306 \
--log-opt max-size=1000m --log-opt max-file=3 \
mysql:8

2 ghost

2.1 数据文件映射

# 启动
docker run -dit --rm --name ghost \
-e NODE_ENV=production \
-e url=https://blog.cooperzhu.com \
-e database__client=mysql \
-e database__connection__host=192.168.1.163 \
-e database__connection__port=3306 \
-e database__connection__user=root \
-e database__connection__password=root \
-e database__connection__database=ghost \
-p 2368:2368 \
--log-opt max-size=1000m --log-opt max-file=3 \
ghost:5

mkdir -p /cz/docker/ghost/data   # 创建目录

# 复制容器的数据文件到主机目录下
docker cp 4e03f25b3e59:/var/lib/ghost/content /cz/docker/ghost/data/content
docker cp 4e03f25b3e59:/var/lib/ghost/content.orig /cz/docker/ghost/data/content.orig

docker stop ghost # 停止

2.2 启动

docker run -dit --rm --name ghost \
-e NODE_ENV=production \
-e url=http://localhost:2368 \
-e database__client=mysql \
-e database__connection__host=192.168.1.163 \
-e database__connection__port=3306 \
-e database__connection__user=root \
-e database__connection__password=root \
-e database__connection__database=ghost \
-p 2368:2368 \
-v /cz/docker/ghost/data/content:/var/lib/ghost/content \
-v /cz/docker/ghost/data/content.orig:/var/lib/ghost/content.orig \
--log-opt max-size=1000m --log-opt max-file=3 \
ghost:5

博客地址:http://localhost:2368

博客后台地址:http://localhost:2368/ghost

2.3 配置

博客后台地址:http://localhost:2368/ghost

2.3.1 为md生成导航目录

tocbot:https://tscanlin.github.io/tocbot/

路径:Settings-->Code injection

下载相关js和css,并上传至content/themes/<主题名称>/assets目录下。

2.3.1.1 Site Header

<script src="/assets/tocbot@4.21.0/tocbot.min.js"></script>
<link href="/assets/tocbot@4.21.0/tocbot.min.css" rel="stylesheet">
<style>
    .gh-content {
        position: relative;
    }

    .gh-toc > .toc-list {
        position: relative;
    }

    .toc-list {
        overflow: hidden;
        list-style: none;
    }
	
	.gh-toc-container li a:first-child::before {
		position: relative;
		content: "|";
		font-weight: bolder;
		margin-right: 0.8rem;
		color: #2d96bd;
	}
	
	.gh-toc-container li a:first-child {
		margin: 0;
	}

    .gh-toc .is-active-link::before {
        background: solid 3px var(--ghost-accent-color); /* Defines TOC accent color based on Accent color set in Ghost Admin */
        font-weight: bolder;
        margin-right: .5rem;
        color: var(--ghost-accent-color);
    }
    
    .gh-toc-container .is-active-link:first-child::before {
        color: var(--ghost-accent-color);
    }
    
    .gh-toc .is-active-link {
        color: var(--ghost-accent-color)
    }

    @media (min-width: 1000px) {
        .gh-sidebar {
            position: absolute; 
            top: 0;
            bottom: 0;
            margin-top: 4vmin;
            margin-left: 20px;
            grid-column: wide-end / main-end; /* Place the TOC to the right of the content */
            width: inline-block;
            white-space: nowrap;
            border-left: 4px solid #f0f0f0;
            padding: 0 .8rem;
            overflow-wrap: break-word;
        }

        .gh-toc-container {
            position: sticky; /* On larger screens, TOC will stay in the same spot on the page */
            top: 4vmin;
            max-width: 300px;
            margin-left: 0.5rem;
        }
        
        .gh-toc-container .gh-toc-toggle {
            display: none;
        }

        .gh-toc-container .gh-toc > .toc-list {
            padding-left: 0; 
            margin-left: 0;
        }
    }

    @media (max-width: 1000px) {
        .gh-toc-container > div {
            background-color: #EDEDED;
        }
        
        .gh-toc-container .gh-toc-title {
            padding-left: 0.8rem;
        }
        
        .gh-toc-container .gh-toc-toggle {
            display: block;
        }
        
        .toc-toggle-arrow {
            border: solid #A9A9B3;
            border-width: 0 3px 3px 0;
            display: inline-block;
            padding: 3px;
            margin: 0.8rem 0;
        }

        .toc-toggle-arrow-right {
            transform: rotate(-45deg);
            -webkit-transform: rotate(-45deg);
        }

        .toc-toggle-arrow-up {
          transform: rotate(-135deg);
          -webkit-transform: rotate(-135deg);
        }
        
        .gh-toc-container .gh-toc {
            display: none;
        }
        .gh-toc-container .gh-toc.show {
            display: block;
            background-color: #F5F5F5;
        }

        .gh-toc-container .gh-toc > .toc-list {
            padding-left: 0; 
            margin-left: 0.8rem;
        }
    }
</style>
<script>
function initTocbot(collapseDepth) {
    tocbot.init({
        tocSelector: '.gh-toc',
        contentSelector: '.gh-content',
        headingSelector: 'h1, h2, h3, h4',
        hasInnerContainers: true,
        collapseDepth: collapseDepth,
    });
}
    
function changeDisplay() {
    // Get the table of contents element
    const toc = document.querySelector(".gh-toc");
    const sidebar = document.querySelector(".gh-sidebar");

    // Check the number of items in the table of contents
    const tocItems = toc.querySelectorAll('li').length;

    // Only show the table of contents if it has more than 5 items
    if (tocItems > 2) {
      sidebar.style.display = 'block';
    } else {
      sidebar.style.display = 'none';
    }
}

/**
<aside class="gh-sidebar">
	<div class="gh-toc-container">
		<div style="font-weight: bold;">
			Table of Contents
			<span style="float: right; margin-right: 0.2rem;"></span>
		</div>
		<div class="gh-toc">
		</div>
	</div>
</aside>
*/
function initSidebar() {
	const parent = document.querySelector(".gh-content.gh-canvas");
    if (!parent) {
        return;
    }
    
	const asideElement = document.createElement("aside");
	asideElement.setAttribute("class", "gh-sidebar");

	// Create the container div for title and TOC
	const containerElement = document.createElement("div");
	containerElement.setAttribute("class", "gh-toc-container");

	// Create the title element
	const titleElement = document.createElement("div");
	titleElement.setAttribute("class", "gh-toc-title");
	titleElement.textContent = "CONTENTS";
	titleElement.style.fontWeight = "bold";
	containerElement.appendChild(titleElement);

	const toggleElement = document.createElement("span");
	toggleElement.setAttribute("class", "gh-toc-toggle toc-toggle-arrow toc-toggle-arrow-right");
	toggleElement.style.float = "right";
	toggleElement.style.marginRight = "0.8rem";
	titleElement.appendChild(toggleElement);


	// Create the <div> element for TOC
	const divElement = document.createElement("div");
	divElement.setAttribute("class", "gh-toc");
	containerElement.appendChild(divElement);
		
	// Append the <div> element to the <aside> element
	asideElement.appendChild(containerElement);
	parent.insertBefore(asideElement, parent.firstChild);
	//parent.appendChild(asideElement);

		
	titleElement.addEventListener("click", function(e) {
		divElement.classList.toggle("show");
		toggleElement.classList.toggle("toc-toggle-arrow-right");
		toggleElement.classList.toggle("toc-toggle-arrow-up");
		
		initTocbot (3);
	});
}

initSidebar();
initTocbot(1);
</script>

2.3.1.3 效果

img

2.3.2 代码块highlight

prism: https://prismjs.com/

路径:Settings-->Code injection

下载相关js和css,并上传至content/themes/<主题名称>/assets目录下。

推荐plugins:

  • Line Numbers
  • Autolinker
  • Show Language
  • Highlight Keywords
  • Inline color
  • Previewers
  • Copy to Clipboard Button

2.3.2.1 Site Header

<script src="/assets/prism/prism.js"></script>
<link rel="stylesheet" href="/assets/prism/prism.css">
<script>
function initPrism() {
    // 初始化Line Numbers plugin
	const children = document.querySelectorAll("pre > code");
    for (var i = 0, len = children.length; i < len; i++) {
    	children[i].parentElement.classList.add("line-numbers");
    }
}
initPrism();
</script>

2.3.2.3 效果

见本文章