Refactor Dockerfile for improved build process; switch to node:20 base image, add build step, and configure volume and port exposure. Update package dependencies for bcrypt and bcryptjs, remove unused files, and enhance README with clearer project structure and setup instructions.

This commit is contained in:
2025-06-18 17:22:40 +02:00
parent dd10624ce4
commit 7e8aa3f498
11 changed files with 591 additions and 678 deletions

3
.dockerignore Normal file
View File

@@ -0,0 +1,3 @@
.next
node_modules
.git

View File

@@ -1,4 +1,4 @@
FROM node:20-alpine
FROM node:20
WORKDIR /app
@@ -8,4 +8,16 @@ RUN npm install
COPY . .
RUN npm run build
VOLUME ["/app/docker"]
EXPOSE 3000
CMD ["npm", "start"]
# Building Instructions
#
# docker build -t markdownblog .
# docker run -p 8080:3000 -v markdownblog-posts:/app/docker markdownblog
# docker container prune

193
README.md
View File

@@ -1,127 +1,102 @@
# Markdown Blog
[![Next.js](https://img.shields.io/badge/Next.js-14-black?style=flat-square&logo=next.js&logoColor=white)](https://nextjs.org/)
[![Tailwind CSS](https://img.shields.io/badge/TailwindCSS-3.4-blue?style=flat-square&logo=tailwind-css&logoColor=white)](https://tailwindcss.com/)
[![TypeScript](https://img.shields.io/badge/TypeScript-5-blue?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
[![Electron](https://img.shields.io/badge/Electron-28-47848F?style=flat-square&logo=electron&logoColor=white)](https://www.electronjs.org/)
[![Docker](https://img.shields.io/badge/Docker-24-2496ED?style=flat-square&logo=docker&logoColor=white)](https://www.docker.com/)
[![MIT License](https://img.shields.io/badge/License-MIT-green?style=flat-square)](LICENSE)
A modern, cross-platform blog system built with **Next.js**, **Markdown**, and **Electron**. Write posts in Markdown, manage content visually, and deploy to web or desktop.
---
## Features
## 🚀 Features
- ✍️ **Markdown-based posts** Write and organize content in Markdown files
- **Hot reloading** — See changes instantly as you edit posts
- 🗂️ **Folder & tag organization** — Structure your content with folders and tags
- 🖥️ **Electron desktop app** — Run your blog as a native desktop app
- 📱 **Responsive UI** — Mobile-friendly and clean design
- 🛠️ **Admin dashboard** — Manage posts and folders visually
- 🐳 **Docker support** — Easy deployment with Docker containers
- Write and organize posts in Markdown
- Visual admin dashboard
- Responsive UI (Tailwind CSS)
- Electron desktop app
- Dockerized deployment with persistent storage
- Secure admin password (bcrypt)
---
## 🚀 Getting Started
## 🛠️ Technologies
- Next.js 14
- TypeScript
- Tailwind CSS
- Electron
- Docker
---
## 📦 Project Structure
```
markdownblog/
├── posts/ # Markdown blog posts
├── src/ # Next.js app code
├── electron/ # Desktop app code
├── public/ # Static assets
├── Dockerfile # Docker configuration
├── .dockerignore # Docker ignore rules
└── manage_container.sh # Docker management script
```
---
## ⚡ Getting Started
### Prerequisites
- [Node.js 18+](https://nodejs.org/)
- [npm](https://www.npmjs.com/)
- [Docker](https://www.docker.com/) (for containerized deployment)
- Node.js 18+
- npm
- Docker (for containerized deployment)
### Installation
---
## 🖥️ Local Development
```bash
git clone
git clone <repo-url>
cd markdownblog
npm install
npm run dev
```
- Visit [http://localhost:3000](http://localhost:3000) in your browser.
### Development
### Build for Production (Local)
- **Web:**
`npm run dev`
- **Desktop (Electron):**
`npm run electron-dev`
### Production
- **Web build:**
`npm run build`
- **Desktop build:**
`npm run electron-build`
```bash
npm run build
npm start
```
---
## 🐳 Docker Deployment
The project includes Docker support for easy deployment. A `manage_container.sh` script is provided to simplify container management.
### Docker Setup
1. Make sure Docker is installed and running on your system
2. Update the `MARKDOWN_DIR` path in `manage_container.sh` to point to your local markdown directory
3. Make the script executable:
```bash
chmod +x manage_container.sh
```
### Container Management
The `manage_container.sh` script provides several commands:
### Build the Docker Image
```bash
# Build the Docker image
./manage_container.sh build
# Start the container
./manage_container.sh start
# Stop the container
./manage_container.sh stop
# Restart the container
./manage_container.sh restart
# View container logs
./manage_container.sh logs
# Check container status
./manage_container.sh status
# Remove the container
./manage_container.sh remove
docker build -t markdownblog .
```
### Container Features
### Run the Container with Persistent Storage
- **Health Checks**: Automatic health monitoring
- **Auto-restart**: Container restarts automatically if it crashes
- **Volume Mounting**: Your markdown files are mounted into the container
- **Port Mapping**: Access the blog at http://localhost:8080
```bash
docker run -p 8080:3000 -v markdownblog-posts:/app/docker markdownblog
```
- The app will be available at [http://localhost:8080](http://localhost:8080)
- All posts are stored persistently in the Docker volume `markdownblog-posts` (mapped to `/app/docker` in the container).
### Container Status
#### Using a Host Directory for Posts
The status command shows:
- Container running state
- Health check status
- Access URL
### Troubleshooting
If the container fails to start:
1. Check the logs: `./manage_container.sh logs`
2. Verify Docker is running
3. Ensure port 8080 is available
4. Check the markdown directory path in `manage_container.sh`
```bash
docker run -p 8080:3000 -v /absolute/path/to/posts:/app/docker markdownblog
```
---
## 📝 Writing Posts
Add Markdown files to the `posts/` directory. Each post should have frontmatter:
- Add Markdown files to the `posts/` directory (or the mounted volume).
- Each post should have frontmatter:
```markdown
---
@@ -136,52 +111,10 @@ Your post content here...
---
## 🗂️ Project Structure
```
markdownblog/
├── posts/ # Markdown blog posts
├── src/
│ ├── app/ # Next.js app directory
│ └── lib/ # Utility functions
├── electron/ # Desktop app code
├── public/ # Static assets (favicons, etc.)
├── Dockerfile # Docker configuration
├── .dockerignore # Docker ignore rules
└── manage_container.sh # Docker management script
```
---
## 🔒 Admin Password Security
- The admin password is stored securely using the bcrypt hashing algorithm (work factor 12, as recommended by [OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)).
- The hash is saved in `posts/admin.json`, which is excluded from git via `.gitignore`.
- Password changes are written atomically to prevent file corruption.
- If the password file is missing or corrupted, the default login is `admin`/`admin` (with a bcrypt hash generated at runtime).
- Passwords longer than 72 bytes are rejected (bcrypt's safe max).
- You can change the admin password from the admin dashboard after logging in.
**Never share or commit your `posts/admin.json` file!**
---
## 🌐 Favicon
Place your favicon files (e.g., `favicon.ico`, `favicon-32x32.png`, `favicon-16x16.png`) in the `public` directory at the project root.
Next.js will automatically serve these at the root URL (e.g., `/favicon.ico`).
---
## 🛠️ Technologies Used
- [Next.js 14](https://nextjs.org/)
- [TypeScript](https://www.typescriptlang.org/)
- [Tailwind CSS](https://tailwindcss.com/)
- [Electron](https://www.electronjs.org/)
- [Remark](https://remark.js.org/) (Markdown)
- [date-fns](https://date-fns.org/)
- [Docker](https://www.docker.com/)
- Admin password is securely hashed with bcrypt and stored in `posts/admin.json`.
- Never commit your `posts/admin.json` file.
---

View File

@@ -1,23 +0,0 @@
⠀⠀⠀⠀⡠⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⢀⠎⠀⠈⠢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠔⠁⠀⢣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⡎⠀⠀⠀⠀⠑⡄⠀⠀⢠⠀⣤⡄⠀⠀⠀⠀⠀⠀⠀⢠⠊⠀⠀⠀⠀⠈⡄⠀⠀⠀⠀⠀⣠⣤⣤⣤⢄⠀⠀
⠀⢰⠁⠀⠀⠀⠀⠀⠈⠢⡀⠈⡄⠀⠀⠉⠒⠄⡀⠀⠀⡠⠃⠀⠀⠀⠀⠀⠀⢃⠀⠀⠀⣴⣯⠟⠛⠻⡝⡗⡀⠀
⠀⡌⠀⠀⠀⠀⠀⠀⠀⠀⠘⢄⡸⠦⠄⠀⠀⠀⠈⠢⡎⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠘⠿⠃⠀⠀⠀⠀⣿⣷
⠀⡇⠀⠀⠀⠀⠀⠀⠀⢴⣊⣁⣀⣀⠤⠀⠀⠀⠀⠀⠈⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⢀⣤⣿⡿
⠀⢰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠇⠀⠀⠀⠀⠀⠀⠀⠀⣞⣿⢟⠁
⠀⠈⢆⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣠⡤⠤⢤⠤⠄⠀⠀⠀⡜⠀⠀⠀⠀⠀⠀⠀⣼⣿⠀⠀⠀⠀
⡀⠀⠈⢆⠀⠈⡟⠁⠈⣿⣿⣿⠁⠀⠀⠀⠀⢸⣿⣿⣷⠀⠀⡇⠀⠀⢀⠜⠀⠀⠀⠀⠀⠀⠀⣿⡇⠀⠀⠀⠀⠀
⠻⡐⠒⠚⠓⠠⡅⠀⠀⣿⣿⣿⠀⠀⠀⠀⠀⠸⣿⣿⡏⠀⠀⣜⠀⠀⠉⠁⡼⠀⠀⠀⠀⠀⠀⠉⠁⠀⠀⠀⠀⠀
⠀⠣⣀⡀⠀⠀⢧⠀⠀⠹⣿⠟⠀⣤⣀⠀⠀⠀⠻⠛⠁⠀⠀⠛⡀⠀⣠⠔⠁⠀⠀⠀⠀⠀⠀⣿⡟⠀⠀⠀⠀⠀
⠀⠀⢠⠃⠘⠹⠔⠓⠀⠀⠀⢀⠀⠀⢀⠀⠀⣠⠀⠀⠀⠚⠭⠚⠁⠀⠈⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⢠⣃⣀⣀⣄⠀⠀⠀⠀⠀⠈⠑⠊⠁⠉⠉⠀⠀⠀⠀⠀⢀⡠⠤⠀⠤⠤⠇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠉⠒⡦⠤⢀⣀⠀⠀⠀⠀⠀⠀⠀⠐⢒⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠈⠢⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢀⣎⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⡆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠎⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⢰⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⡸⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
Why are you gay?

959
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -29,7 +29,8 @@
"typescript": "^5.3.3",
"date-fns": "^3.6.0",
"@tailwindcss/typography": "^0.5.16",
"bcrypt": "^6.0.0"
"bcryptjs": "^2.4.3",
"bcrypt": "^5.0.2"
},
"devDependencies": {
"@types/dompurify": "^3.0.5",
@@ -38,6 +39,6 @@
"concurrently": "^8.2.2",
"eslint": "^8.57.0",
"eslint-config-next": "14.1.0",
"@types/bcrypt": "^5.0.2"
"@types/bcryptjs": "^2.4.6"
}
}

View File

@@ -1,14 +0,0 @@
module.exports = {
apps: [
{
name: "markdownblog-dev",
script: "npm",
args: "run dev",
watch: true,
env: {
NODE_ENV: "development",
PORT: 8080
}
}
]
};

View File

@@ -1,6 +0,0 @@
#!/bin/bash
npm install
npm run build
PORT=8080 npm start &
echo "server running on port 8080"
wait

View File

@@ -1,7 +1,7 @@
import { NextResponse } from 'next/server';
import fs from 'fs';
import path from 'path';
import bcrypt from 'bcrypt';
import bcrypt from 'bcryptjs';
const adminPath = path.join(process.cwd(), 'posts', 'admin.json');
const tempPath = path.join(process.cwd(), 'posts', 'admin.json.tmp');

View File

@@ -68,17 +68,13 @@ export default function RootLayout({
</div>
</header>
{children}
<footer className="bg-gray-100 p-4">
<footer className="bg-gray-100 p-2">
<div className="container mx-auto flex flex-col md:flex-row justify-between items-center">
<p>
<span>
&copy; {new Date().getFullYear()} {blogOwner}
</span>
<span className="text-gray-500 text-right" style={{ fontSize: '12px' }}>
Du bist auf dem Development-Server.
Er ist nicht stabil und kann sich jederzeit ändern.
</span>
</p>
<div className="text-center">
<span className="text-gray-500" style={{ fontSize: '12px' }}>
&copy; {new Date().getFullYear()} {blogOwner}
</span>
</div>
</div>
</footer>
</body>

View File

@@ -1,32 +0,0 @@
#!/bin/bash
# Check the command line argument
case "$1" in
autodeploy)
echo "Starting PM2 with auto-deployment..."
pm2 start pm2.config.js
;;
prod)
echo "Starting PM2 with production build..."
NODE_ENV=production pm2 start pm2.config.js
;;
stop)
echo "Stopping PM2 process..."
pm2 stop all
;;
restart)
echo "Restarting PM2 process..."
pm2 restart all
;;
status)
echo "Showing PM2 process status..."
pm2 status
;;
logs)
echo "Showing PM2 logs..."
pm2 logs
;;
*)
echo "Usage: ./start_pm2 {autodeploy|prod|stop|restart|status|logs}"
;;
esac