A full-stack blog application with Go backend and Next.js frontend, containerized with Docker for easy deployment.
Deploy directly from Docker Hub without cloning the repository:
curl -sSL https://raw.githubusercontent.com/xuemian168/i18n_blog/main/deploy-from-hub.sh -o deploy.sh && chmod +x deploy.sh && ./deploy.sh
Note: Interactive scripts should not be piped directly to bash. Download and execute locally to ensure proper functionality.
Or manually with Docker:
docker run -d \
--name i18n_blog \
-p 80:80 \
-v $(pwd)/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-domain.com/api \
ictrun/i18n_blog:latest
Clone the repository:
git clone <repository-url>
cd blog
Start the application:
./start.sh
Access the application:
# Download the compose file
curl -O https://raw.githubusercontent.com/xuemian168/i18n_blog/main/docker-compose.hub.yml
# Configure environment
cp .env.hub.example .env
# Edit .env with your settings
# Deploy
docker-compose -f docker-compose.hub.yml up -d
docker run -d \
--name i18n_blog \
--restart unless-stopped \
-p 80:80 \
-v blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-api-domain.com/api \
-e DB_PATH=/app/data/blog.db \
ictrun/i18n_blog:latest
ictrun/i18n_blog:latest - Latest stable releaseictrun/i18n_blog:v1.0.0 - Specific versionictrun/i18n_blog:develop - Development branch| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_API_URL | https://your-domain.com/api | Your API endpoint URL |
DB_PATH | /app/data/blog.db | SQLite database path |
GIN_MODE | release | Go Gin mode (release/debug) |
NODE_ENV | production | Node.js environment |
RECOVERY_MODE | false | Password recovery mode |
adminxuemian168# Check status
docker ps | grep i18n_blog
# View logs
docker logs i18n_blog
# Backup data
docker cp i18n_blog:/app/data ./backup-data
# Stop and remove
docker stop i18n_blog
docker rm i18n_blog
To upgrade your Docker deployment while preserving all data:
# Create backup directory
mkdir -p ./backups/$(date +%Y%m%d_%H%M%S)
# Backup the data volume
docker run --rm -v blog-data:/data -v $(pwd)/backups/$(date +%Y%m%d_%H%M%S):/backup alpine sh -c "cd /data && tar czf /backup/blog-data-backup.tar.gz ."
# Or if using bind mount, simply copy the directory
cp -r ./blog-data ./backups/$(date +%Y%m%d_%H%M%S)/
docker pull ictrun/i18n_blog:latest
docker stop i18n_blog
docker rm i18n_blog
# If using named volume (recommended)
docker run -d \
--name i18n_blog \
--restart unless-stopped \
-p 80:80 \
-v blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-domain.com/api \
-e DB_PATH=/app/data/blog.db \
ictrun/i18n_blog:latest
# If using bind mount
docker run -d \
--name i18n_blog \
--restart unless-stopped \
-p 80:80 \
-v $(pwd)/blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-domain.com/api \
-e DB_PATH=/app/data/blog.db \
ictrun/i18n_blog:latest
# Check container status
docker ps | grep i18n_blog
# Check logs for any errors
docker logs i18n_blog
# Test the application
curl -f http://localhost/api/categories || echo "API check failed"
To upgrade your Docker Compose deployment while preserving all data:
# Create backup directory
mkdir -p ./backups/$(date +%Y%m%d_%H%M%S)
# Stop services temporarily for consistent backup
docker-compose stop
# Backup the data volume
docker run --rm -v blog_blog_data:/data -v $(pwd)/backups/$(date +%Y%m%d_%H%M%S):/backup alpine sh -c "cd /data && tar czf /backup/blog-data-backup.tar.gz ."
# Or backup the entire compose environment
cp -r ./data ./backups/$(date +%Y%m%d_%H%M%S)/ 2>/dev/null || true
cp docker-compose.yml ./backups/$(date +%Y%m%d_%H%M%S)/ 2>/dev/null || true
cp .env ./backups/$(date +%Y%m%d_%H%M%S)/ 2>/dev/null || true
# Restart services
docker-compose start
docker-compose pull
# Method 1: Rolling update (recommended for production)
docker-compose up -d --force-recreate --remove-orphans
# Method 2: Complete restart (if you need to stop everything)
docker-compose down && docker-compose up -d
# Remove unused images to free up space
docker image prune -f
# Or remove specific old images
docker images | grep i18n_blog | grep -v latest | awk '{print $3}' | xargs docker rmi 2>/dev/null || true
# Check all services status
docker-compose ps
# Check logs for any errors
docker-compose logs -f --tail=50
# Test the application
curl -f http://localhost:3000 || echo "Frontend check failed"
curl -f http://localhost:8080/api/categories || echo "API check failed"
For convenience, you can create an automated upgrade script:
#!/bin/bash
# save as upgrade-docker.sh
set -e
echo "๐ Starting Docker deployment upgrade..."
# Configuration
CONTAINER_NAME="i18n_blog"
IMAGE_NAME="ictrun/i18n_blog:latest"
BACKUP_DIR="./backups/$(date +%Y%m%d_%H%M%S)"
# Create backup
echo "๐ฆ Creating backup..."
mkdir -p "$BACKUP_DIR"
docker run --rm -v blog-data:/data -v "$BACKUP_DIR":/backup alpine sh -c "cd /data && tar czf /backup/blog-data-backup.tar.gz ."
# Pull latest image
echo "โฌ๏ธ Pulling latest image..."
docker pull "$IMAGE_NAME"
# Stop and remove old container
echo "๐ Stopping old container..."
docker stop "$CONTAINER_NAME" 2>/dev/null || true
docker rm "$CONTAINER_NAME" 2>/dev/null || true
# Start new container
echo "๐ Starting new container..."
docker run -d \
--name "$CONTAINER_NAME" \
--restart unless-stopped \
-p 80:80 \
-v blog-data:/app/data \
-e NEXT_PUBLIC_API_URL="${NEXT_PUBLIC_API_URL:-http://localhost/api}" \
-e DB_PATH=/app/data/blog.db \
"$IMAGE_NAME"
# Verify
echo "โ
Verifying upgrade..."
sleep 10
if docker ps | grep -q "$CONTAINER_NAME"; then
echo "โ
Upgrade completed successfully!"
echo "๐ Backup saved to: $BACKUP_DIR"
else
echo "โ Upgrade failed! Check logs: docker logs $CONTAINER_NAME"
exit 1
fi
#!/bin/bash
# save as upgrade-compose.sh
set -e
echo "๐ Starting Docker Compose deployment upgrade..."
# Configuration
BACKUP_DIR="./backups/$(date +%Y%m%d_%H%M%S)"
# Create backup
echo "๐ฆ Creating backup..."
mkdir -p "$BACKUP_DIR"
docker-compose stop
docker run --rm -v blog_blog_data:/data -v "$BACKUP_DIR":/backup alpine sh -c "cd /data && tar czf /backup/blog-data-backup.tar.gz ."
cp -r ./data "$BACKUP_DIR/" 2>/dev/null || true
cp docker-compose.yml "$BACKUP_DIR/" 2>/dev/null || true
cp .env "$BACKUP_DIR/" 2>/dev/null || true
# Pull and upgrade
echo "โฌ๏ธ Pulling latest images..."
docker-compose pull
echo "๐ Upgrading services..."
docker-compose up -d --force-recreate --remove-orphans
# Clean up
echo "๐งน Cleaning up old images..."
docker image prune -f
# Verify
echo "โ
Verifying upgrade..."
sleep 15
if docker-compose ps | grep -q "Up"; then
echo "โ
Upgrade completed successfully!"
echo "๐ Backup saved to: $BACKUP_DIR"
else
echo "โ Upgrade failed! Check logs: docker-compose logs"
exit 1
fi
If an upgrade fails, you can rollback to the previous version:
# Stop the failed container
docker stop i18n_blog && docker rm i18n_blog
# Restore from backup (if needed)
docker run --rm -v blog-data:/data -v $(pwd)/backups/BACKUP_DATE:/backup alpine sh -c "cd /data && tar xzf /backup/blog-data-backup.tar.gz"
# Run the previous image version
docker run -d \
--name i18n_blog \
--restart unless-stopped \
-p 80:80 \
-v blog-data:/app/data \
-e NEXT_PUBLIC_API_URL=https://your-domain.com/api \
ictrun/i18n_blog:PREVIOUS_TAG
# Edit docker-compose.yml to use previous image tag
# Then restart
docker-compose down
docker-compose up -d
# Restore data if needed
docker-compose stop
docker run --rm -v blog_blog_data:/data -v $(pwd)/backups/BACKUP_DATE:/backup alpine sh -c "cd /data && tar xzf /backup/blog-data-backup.tar.gz"
docker-compose start
docker-compose up --build -d
docker-compose -f docker-compose.prod.yml up --build -d
./data/blog.dbGET /api/articles - List all articlesPOST /api/articles - Create articleGET /api/articles/:id - Get article by IDPUT /api/articles/:id - Update articleDELETE /api/articles/:id - Delete articlePOST /api/articles/import - Import markdownGET /api/categories - List all categoriesPOST /api/categories - Create categoryGET /api/categories/:id - Get category by IDPUT /api/categories/:id - Update categoryDELETE /api/categories/:id - Delete categoryGET /api/settings - Get site settingsPUT /api/settings - Update site settingsThe application uses a unified configuration approach. Copy .env.example to .env and modify as needed:
# Backend Configuration
DB_PATH=./data/blog.db
GIN_MODE=release
PORT=8080
RECOVERY_MODE=false
# Frontend Configuration
NEXT_PUBLIC_API_URL=https://yourdomain.com/api
NODE_ENV=production
PORT=3000
NEXT_PUBLIC_API_URL environment variable.http://localhost:8080/api.Local Development:
NEXT_PUBLIC_API_URL=http://localhost:8080/api
Production:
NEXT_PUBLIC_API_URL=https://yourdomain.com/api
The frontend will automatically use:
https://yourdomain.com/api/*https://yourdomain.comblog_data: Persistent storage for SQLite database./start.sh
./stop.sh
docker-compose logs -f
docker-compose restart
docker-compose down -v
docker system prune -f
If you forget the admin password, follow these steps to reset it safely:
./stop.sh
Edit your .env file and set:
RECOVERY_MODE=true
./start.sh
The system will:
xuemian168Edit your .env file and set:
RECOVERY_MODE=false
./start.sh
Now you can login with:
adminxuemian168http://localhost:3000/adminโ ๏ธ Important Security Considerations:
Problem: System won't start after enabling recovery mode Solution: This is intentional. Check the logs to confirm password was reset, then disable recovery mode.
Problem: Can't find the .env file
Solution: Copy .env.example to .env first, then modify the RECOVERY_MODE setting.
Problem: Recovery mode doesn't reset password
Solution: Ensure the environment variable is set correctly (RECOVERY_MODE=true) and check Docker logs for error messages.
cd backend
go mod download
go run cmd/server/main.go
cd frontend
npm install
npm run dev
cd backend
go build -o bin/server cmd/server/main.go
cd frontend
npm run build
npm start
sudo if needed on Linuxdocker system prune -fcurl | bash fails with "syntax error near unexpected token 'fi'"curl -sSL https://raw.githubusercontent.com/xuemian168/i18n_blog/main/deploy-from-hub.sh -o deploy.sh && chmod +x deploy.sh && ./deploy.shNEXT_PUBLIC_API_URL is setdocker logs container-name to see "Setting runtime API URL to: your-url"The application includes health checks for both services:
http://localhost:8080/api/categorieshttp://localhost:3000View service logs:
# All services
docker-compose logs -f
# Specific service
docker-compose logs -f backend
docker-compose logs -f frontend
docker-compose.prod.yml for productionssl directoryMIT License
Content type
Image
Digest
sha256:5b90dea83โฆ
Size
120 MB
Last updated
about 1 year ago
docker pull ictrun/i18n_blog