docker部署memos轻量级备忘录

方案一:基础Docker部署

1. 使用官方镜像快速启动

# 创建数据目录
mkdir -p ~/memos

# 运行Memos容器
docker run -d \
  --name memos \
  -p 5230:5230 \
  -v ~/memos/.memos/:/var/opt/memos \
  ghcr.io/usememos/memos:latest

2. 使用Docker Compose(推荐)

创建 docker-compose.yml 文件:

version: '3.8'
services:
  memos:
    image: ghcr.io/usememos/memos:latest
    container_name: memos
    restart: unless-stopped
    ports:
      - "5230:5230"
    volumes:
      - ./data:/var/opt/memos
    environment:
      - TZ=Asia/Shanghai  # 设置时区

启动服务:

docker-compose up -d

方案二:高级配置

1. 包含环境变量的完整配置

version: '3.8'
services:
  memos:
    image: ghcr.io/usememos/memos:latest
    container_name: memos
    restart: unless-stopped
    ports:
      - "5230:5230"
    volumes:
      - memos_data:/var/opt/memos
    environment:
      - TZ=Asia/Shanghai
      - MEMOS_MODE=prod  # 生产模式
      - MEMOS_PORT=5230
      # 可选:使用外部数据库(默认为SQLite)
      # - MEMOS_DRIVER=postgres
      # - MEMOS_DSN="postgres://user:password@postgres:5432/memos?sslmode=disable"
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5230/api/v1/status"]
      interval: 30s
      timeout: 10s
      retries: 3

volumes:
  memos_data:

2. 使用外部PostgreSQL数据库

version: '3.8'
services:
  postgres:
    image: postgres:15-alpine
    container_name: memos_postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: memos
      POSTGRES_PASSWORD: your_password_here
      POSTGRES_DB: memos
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U memos"]
      interval: 10s
      timeout: 5s
      retries: 5

  memos:
    image: ghcr.io/usememos/memos:latest
    container_name: memos
    restart: unless-stopped
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "5230:5230"
    environment:
      - MEMOS_MODE=prod
      - MEMOS_DRIVER=postgres
      - MEMOS_DSN=postgres://memos:your_password_here@postgres:5432/memos?sslmode=disable
    volumes:
      - ./resources:/var/opt/memos/resources  # 只存储资源文件

volumes:
  postgres_data:

方案三:使用Nginx反向代理

1. Docker Compose + Nginx配置

version: '3.8'
services:
  memos:
    image: ghcr.io/usememos/memos:latest
    container_name: memos
    restart: unless-stopped
    expose:
      - "5230"
    environment:
      - MEMOS_MODE=prod
    volumes:
      - ./data:/var/opt/memos

  nginx:
    image: nginx:alpine
    container_name: memos_nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl  # SSL证书目录
    depends_on:
      - memos

2. Nginx配置文件 (nginx.conf)

events {
    worker_connections 1024;
}

http {
    upstream memos {
        server memos:5230;
    }

    server {
        listen 80;
        server_name your-domain.com;
        
        # 重定向到HTTPS
        return 301 https://$server_name$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name your-domain.com;

        # SSL证书路径
        ssl_certificate /etc/nginx/ssl/your-domain.com.crt;
        ssl_certificate_key /etc/nginx/ssl/your-domain.com.key;
        
        # SSL优化配置
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers off;

        # 反向代理配置
        location / {
            proxy_pass http://memos;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            
            # 超时设置
            proxy_connect_timeout 60s;
            proxy_send_timeout 60s;
            proxy_read_timeout 60s;
        }

        # 静态文件缓存
        location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
            proxy_pass http://memos;
            proxy_cache_valid 200 302 1h;
            proxy_cache_valid 404 1m;
        }
    }
}

方案四:使用Traefik反向代理(推荐用于生产环境)

version: '3.8'
services:
  memos:
    image: ghcr.io/usememos/memos:latest
    container_name: memos
    restart: unless-stopped
    expose:
      - "5230"
    environment:
      - MEMOS_MODE=prod
    volumes:
      - ./data:/var/opt/memos
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.memos.rule=Host(`memos.your-domain.com`)"
      - "traefik.http.routers.memos.entrypoints=websecure"
      - "traefik.http.routers.memos.tls.certresolver=myresolver"
      - "traefik.http.services.memos.loadbalancer.server.port=5230"

  traefik:
    image: traefik:v2.10
    container_name: traefik
    restart: unless-stopped
    command:
      - "--api.dashboard=true"
      - "--providers.docker=true"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.tlschallenge=true"
      - "--certificatesresolvers.myresolver.acme.email=your-email@example.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"

常用管理命令

# 查看容器状态
docker ps

# 查看日志
docker logs memos
docker logs -f memos  # 实时查看

# 进入容器
docker exec -it memos sh

# 重启服务
docker restart memos

# 停止服务
docker stop memos

# 启动服务
docker start memos

# 删除容器(数据会保留在卷中)
docker rm memos

# 更新Memos
docker pull ghcr.io/usememos/memos:latest
docker stop memos
docker rm memos
# 然后重新运行部署命令

备份和恢复

备份数据

# 如果使用默认SQLite
docker cp memos:/var/opt/memos/memos_prod.db ./backup/

# 如果使用卷
docker run --rm -v memos_data:/data -v $(pwd):/backup alpine \
  tar czf /backup/memos_backup_$(date +%Y%m%d).tar.gz -C /data .

恢复数据

# 停止Memos容器
docker stop memos

# 恢复数据
docker run --rm -v memos_data:/data -v $(pwd):/backup alpine \
  tar xzf /backup/memos_backup.tar.gz -C /data

# 启动Memos
docker start memos

故障排除

  1. 端口冲突:如果5230端口被占用,可以修改映射端口

    ports:
      - "8080:5230"  # 外部端口:内部端口
    
  2. 权限问题:如果容器无法写入数据,可以设置正确的权限

    chmod 755 ./data
    
  3. 内存限制:可以设置容器资源限制

    memos:
      # ...
      deploy:
        resources:
          limits:
            memory: 512M
            cpus: '1.0'