1. 项目概述为什么选择容器化部署YOURLS如果你正在寻找一个自建短链接服务的方案YOURLSYour Own URL Shortener大概率已经进入了你的视野。它是一个用PHP写的、开源的、功能强大的短链接系统。但传统的部署方式——在服务器上配置LAMPLinux, Apache, MySQL, PHP或LEMP环境——对于很多开发者尤其是运维经验不那么丰富的朋友来说是个不小的门槛。你需要操心PHP版本、MySQL配置、Apache/Nginx的虚拟主机设置还有各种文件权限问题。这正是官方推出容器镜像的意义所在。ghcr.io/yourls/yourls这个镜像把YOURLS及其运行环境包括特定版本的PHP和必要的扩展打包成了一个标准化的“集装箱”。这意味着无论你的服务器是Ubuntu、CentOS还是Alpine只要它能运行Docker或任何兼容OCIOpen Container Initiative标准的容器运行时比如Podman你就能以几乎完全相同的方式在几分钟内启动一个功能完整的YOURLS服务。这极大地降低了部署复杂度提升了环境的一致性和可移植性。简单来说它把“安装配置一个Web应用”这件事简化成了“拉取一个镜像并运行它”。2. 核心架构与镜像解析2.1 镜像技术栈与版本策略官方YOURLS容器镜像基于一个精心挑选的基础镜像构建。从Dockerfile的历史记录来看它通常基于php:${PHP_VERSION}-apache这个官方镜像变体。这个选择非常务实集成Apache省去了单独安装和配置Web服务器如Nginx的步骤。Apache的.htaccess文件支持也让YOURLS的某些插件特别是涉及URL重写的可以开箱即用减少了配置复杂度。官方PHP镜像确保了PHP环境的安全性和稳定性能及时获得安全更新。镜像本身基于Debian或Alpine提供了可靠的底层系统。扩展齐全镜像已经预装了YOURLS运行所必需的PHP扩展例如mysqli或pdo_mysql用于连接MySQL/MariaDB、gd用于图形处理可能用于验证码或统计图表、zip用于插件/主题管理等。关于版本你需要关注两个标签具体版本标签如ghcr.io/yourls/yourls:1.9.2。这对应着YOURLS的具体发行版。这是生产环境的首选因为它能确保应用行为的确定性。浮动标签如ghcr.io/yourls/yourls:latest。它总是指向最新的稳定版。适合开发测试环境但在生产环境中应避免使用以防意外升级带来兼容性问题。2.2 容器内的目录结构与数据持久化理解容器内的文件布局对于正确配置和持久化数据至关重要。容器启动后关键目录如下/var/www/html/这是YOURLS应用代码的根目录。所有PHP文件、admin后台目录、user插件目录等都位于此处。/var/www/html/user/config.php这是最关键的配置文件。YOURLS容器通过环境变量来动态生成这个文件这是容器化部署的核心机制。这里有一个必须明确的重要原则容器本身是无状态的。当容器被删除或重新创建时其内部文件系统的所有更改都会丢失。因此我们必须将需要持久化的数据“映射”到宿主机上。需要持久化的数据主要有两类用户配置与插件数据即/var/www/html/user/目录下的所有内容。这里面包含了你的config.php由环境变量生成、安装的插件、主题以及插件产生的数据。上传文件如果使用了支持文件上传的插件例如一个允许自定义短链接二维码Logo的插件这些上传的文件也需要持久化。在Docker中我们通过-v或--mount参数将宿主机的目录“挂载”到容器内的对应路径来实现数据持久化。3. 从零开始的完整部署实操下面我将演示如何使用Docker Compose来部署一个包含YOURLS和MySQL数据库的完整服务栈。这是目前最推荐的方式因为它用声明式的YAML文件定义了整个应用管理起来非常方便。3.1 准备工作与环境要求首先确保你的服务器或本地开发机已经安装了Docker Engine版本建议在20.10以上。Docker Compose虽然现在Docker Compose已集成到Docker CLI (docker compose)但为了兼容性我们使用独立的docker-compose命令。建议版本在2.0以上。你可以通过运行docker --version和docker-compose --version来检查。接下来在服务器上创建一个项目目录例如~/yourls-docker所有操作都将在这个目录下进行。mkdir -p ~/yourls-docker cd ~/yourls-docker3.2 编写Docker Compose配置文件创建一个名为docker-compose.yml的文件内容如下。我会逐段解释关键配置。version: 3.8 services: # 数据库服务 db: image: mariadb:10.11 container_name: yourls_db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: your_strong_root_password_here # 务必修改 MYSQL_DATABASE: yourls MYSQL_USER: yourls MYSQL_PASSWORD: your_strong_database_password_here # 务必修改 volumes: - db_data:/var/lib/mysql - ./mysql-init:/docker-entrypoint-initdb.d:ro networks: - yourls_net healthcheck: test: [CMD, healthcheck.sh, --connect, --innodb_initialized] interval: 10s timeout: 5s retries: 3 # YOURLS应用服务 yourls: image: ghcr.io/yourls/yourls:1.9.2 # 指定一个稳定版本 container_name: yourls_app restart: unless-stopped ports: - 8080:80 # 将宿主机的8080端口映射到容器的80端口 environment: # 数据库连接配置 (必须与上面db服务中的设置对应) YOURLS_DB_HOST: db YOURLS_DB_USER: yourls YOURLS_DB_PASS: your_strong_database_password_here YOURLS_DB_NAME: yourls YOURLS_DB_PREFIX: yourls_ # 站点配置 (根据你的实际情况修改) YOURLS_SITE: https://short.yourdomain.com # 你的短域名 YOURLS_COOKIEKEY: your-very-long-secret-random-string-here # 用于加密cookie务必用长随机字符串 # 管理员账户 YOURLS_USER: admin # 管理员用户名 YOURLS_PASS: your-strong-admin-password # 管理员密码建议用密码生成器生成 # 其他可选配置 YOURLS_LANG: zh_CN # 设置为中文界面 YOURLS_UNIQUE_URLS: true # 确保短链接唯一性 YOURLS_PRIVATE: true # 设为true表示需要登录才能查看统计false则公开 volumes: # 持久化用户数据配置、插件、上传文件 - yourls_data:/var/www/html/user # 如果你想自定义Apache配置或PHP配置可以挂载配置文件 # - ./apache-site.conf:/etc/apache2/sites-available/000-default.conf:ro # - ./php-overrides.ini:/usr/local/etc/php/conf.d/99-overrides.ini:ro depends_on: db: condition: service_healthy # 等待数据库健康检查通过后再启动 networks: - yourls_net # 定义网络让两个容器在同一个隔离网络内通信更安全 networks: yourls_net: driver: bridge # 定义数据卷用于持久化数据 volumes: db_data: # MySQL/MariaDB的数据卷 yourls_data: # YOURLS的用户数据卷关键配置解读与注意事项密码安全示例中的your_strong_root_password_here、your_strong_database_password_here和your-strong-admin-password必须替换为你自己生成的强密码。对于YOURLS_COOKIEKEY可以使用命令openssl rand -base64 48来生成一个安全的随机字符串。网络我们创建了一个自定义的桥接网络yourls_net。这样yourls容器可以通过服务名db直接访问数据库容器无需暴露数据库端口到宿主机更安全。数据卷db_data和yourls_data是Docker管理的命名卷数据存储在Docker的特定区域。你也可以使用绑定挂载如./yourls_user_data:/var/www/html/user将数据存在当前目录方便备份。生产环境更推荐命名卷性能和管理更优。健康检查为db服务配置了healthcheck并且yourls服务通过condition: service_healthy依赖它。这确保了应用容器不会在数据库准备好之前启动避免了启动时报数据库连接错误。端口映射- 8080:80将容器的80端口映射到宿主机的8080端口。在生产环境你通常不会直接暴露这个端口而是会在前面放一个Nginx或Caddy作为反向代理处理SSLHTTPS和域名绑定。3.3 启动服务与初始化访问配置文件准备好后在~/yourls-docker目录下执行一条命令即可启动所有服务docker-compose up -d-d参数表示在后台运行。Docker会拉取镜像如果本地没有然后按顺序启动容器。使用以下命令查看容器状态和日志# 查看容器运行状态 docker-compose ps # 查看实时日志特别是启动初期用于排错 docker-compose logs -f yourls # 或者查看所有服务的日志 docker-compose logs -f当看到yourls_app和yourls_db状态均为Up (healthy)后就可以通过浏览器访问了。临时访问打开浏览器访问http://你的服务器IP:8080/admin/。你应该会被重定向到安装界面。由于我们已经通过环境变量提供了所有配置YOURLS会自动检测并完成安装直接跳转到登录页面。用你设置的YOURLS_USER和YOURLS_PASS登录即可。正式访问生产环境你需要在域名DNS中将你的短域名如short.yourdomain.com解析到服务器IP然后在宿主机上配置一个反向代理如Nginx将对该域名的HTTPS请求代理到localhost:8080即Docker映射的端口。这是实现HTTPS和隐藏端口的关键步骤。4. 高级配置、优化与日常运维4.1 通过环境变量深度定制YOURLS容器镜像支持大量的环境变量远超上面示例中的几个。掌握它们可以让你深度定制实例。核心功能开关YOURLS_PUBLIC与YOURLS_PRIVATE相对。设置为true时即使未登录用户也可以访问短链接并查看公开的统计信息如果插件支持。YOURLS_DEBUG: 设置为true可以在页面底部显示调试信息开发时有用。链接行为控制YOURLS_URL_CONVERT: 设置URL编码算法62或64。除非有特殊兼容性需求一般不用改。YOURLS_RESERVED_URLS: 定义保留的关键词短码防止被占用。可以通过环境变量设置格式如word1,word2,admin。邮件配置用于找回密码等environment: YOURLS_SMTP_HOST: smtp.gmail.com YOURLS_SMTP_PORT: 587 YOURLS_SMTP_USER: your-emailgmail.com YOURLS_SMTP_PASS: your-app-specific-password # 注意不要用邮箱主密码 YOURLS_SMTP_SECURE: tls # 或 ssl YOURLS_SMTP_FROM: your-emailgmail.com YOURLS_SMTP_FROM_NAME: YOURLS Service重要提示对于Gmail等邮箱通常需要开启“两步验证”并生成“应用专用密码”来填写YOURLS_SMTP_PASS直接使用邮箱密码会失败。4.2 性能优化与安全加固建议使用.env文件管理敏感信息将docker-compose.yml中的所有密码、密钥等敏感信息移出放到一个名为.env的文件中该文件默认被.gitignore忽略。docker-compose.yml中则引用变量。.env文件内容示例MYSQL_ROOT_PASSWORDsupersecretroot MYSQL_PASSWORDstrongdbpass YOURLS_COOKIEKEY$(openssl rand -base64 48) YOURLS_PASSadminstrongpass在docker-compose.yml中引用YOURLS_PASS: ${YOURLS_PASS}配置反向代理与HTTPS生产环境必须使用HTTPS。可以使用Nginx或Caddy作为反向代理。Nginx配置片段示例(/etc/nginx/sites-available/short.yourdomain.com)server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name short.yourdomain.com; # SSL证书路径使用Let‘s Encrypt或商业证书 ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; location / { proxy_pass http://localhost:8080; # 指向Docker映射的端口 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; # 如果YOURLS配置了HTTPS需要告诉它真实的协议 proxy_set_header X-Forwarded-Ssl on; } }使用Caddy更简单自动HTTPSCaddyfile配置极其简单short.yourdomain.com { reverse_proxy localhost:8080 }Caddy会自动从Let‘s Encrypt申请并续期SSL证书。镜像更新策略不要盲目使用latest标签。定期检查YOURLS的官方发布页。更新时步骤通常是# 拉取新版本镜像 docker-compose pull yourls # 重启服务Compose会使用新镜像重新创建容器 docker-compose up -d # 查看日志确认无异常 docker-compose logs -f yourls更新前务必备份数据卷4.3 数据备份与恢复备份是运维的生命线。由于我们使用了Docker卷备份过程很清晰。备份# 进入项目目录 cd ~/yourls-docker # 停止服务以避免数据写入不一致对于短链接服务短暂停机是可接受的 docker-compose down # 备份数据库卷 docker run --rm -v yourls-docker_db_data:/source -v $(pwd):/backup alpine tar czf /backup/db_backup_$(date %Y%m%d).tar.gz -C /source . # 备份YOURLS用户数据卷 docker run --rm -v yourls-docker_yourls_data:/source -v $(pwd):/backup alpine tar czf /backup/yourls_data_backup_$(date %Y%m%d).tar.gz -C /source . # 重新启动服务 docker-compose up -d这个操作会创建两个压缩包在当前目录。你应该将这些备份文件传输到异地存储如云存储、另一台服务器。恢复# 假设你要恢复到某个备份日期的状态 cd ~/yourls-docker # 停止服务 docker-compose down # 删除现有数据卷谨慎操作确认备份文件可用 docker volume rm yourls-docker_db_data yourls-docker_yourls_data # 重新创建空卷Compose up时会自动创建 # 启动服务此时是空的 docker-compose up -d db yourls # 等待数据库容器完全启动后停止应用容器保持数据库运行 docker-compose stop yourls # 恢复数据库数据 docker run --rm -v yourls-docker_db_data:/target -v $(pwd):/backup alpine sh -c rm -rf /target/* tar xzf /backup/db_backup_20231027.tar.gz -C /target # 恢复YOURLS用户数据 docker run --rm -v yourls-docker_yourls_data:/target -v $(pwd):/backup alpine sh -c rm -rf /target/* tar xzf /backup/yourls_data_backup_20231027.tar.gz -C /target # 重新启动所有服务 docker-compose up -d5. 常见问题与故障排查实录即使按照步骤操作也可能会遇到一些问题。下面是我在多次部署中遇到的典型问题及解决方法。5.1 容器启动失败与日志分析问题现象执行docker-compose up -d后docker-compose ps显示容器状态不是Up可能是Exit 1或Restarting。排查步骤查看详细日志这是最重要的第一步。运行docker-compose logs yourls。错误信息通常会直接显示出来。常见错误1数据库连接失败日志信息SQLSTATE[HY000] [2002] Connection refused或php_network_getaddresses: getaddrinfo failed: Name does not resolve。原因YOURLS容器无法解析或连接到db这个主机名。解决确认docker-compose.yml中yourls服务的YOURLS_DB_HOST值就是db数据库服务的名称。确认两个服务在同一个自定义网络yourls_net下。检查db容器是否健康运行docker-compose logs db查看MariaDB初始化是否有错误。可能是数据库尚未完全初始化好YOURLS就尝试连接了。确保使用了depends_on的condition: service_healthy配置如前文示例并给数据库足够启动时间。常见错误2环境变量未生效或config.php生成失败日志信息可能没有明显错误但访问页面提示“需要配置YOURLS”或直接白屏。解决进入容器内部检查配置文件docker-compose exec yourls cat /var/www/html/user/config.php。如果文件内容不是根据你的环境变量生成的或者文件不存在说明环境变量传递或容器启动脚本有问题。检查环境变量名是否拼写错误特别是YOURLS_DB_PASS和YOURLS_PASS是否混淆。尝试删除yourls_data数据卷并重启让容器重新生成配置docker-compose down -v警告这会删除所有数据仅限初次调试然后docker-compose up -d。5.2 后台登录与权限问题问题现象可以访问后台登录页但输入正确的用户名密码后无法登录或提示“无效的管理员凭证”。排查步骤确认密码在docker-compose.yml或.env文件中YOURLS_PASS的值是你设定的密码。注意YOURLS使用的是MD5哈希但容器启动脚本会处理。确保密码字符串没有多余的空格或换行符。检查Cookie密钥YOURLS_COOKIEKEY是用于加密会话的重要密钥。如果它被更改之前的登录会话会失效。确保其值稳定不变。如果你重建了容器且使用了新的随机密钥就需要用新密钥重新登录。手动重置密码终极方法如果忘记密码或环境变量方式始终不行可以通过直接操作数据库来重置。首先进入数据库容器docker-compose exec db mysql -u root -p输入MYSQL_ROOT_PASSWORD。选择数据库USE yourls;查看当前用户SELECT * FROM yourls_options WHERE option_name yourls_passwords;。这个字段存储着序列化的用户密码哈希。更简单的方法是使用YOURLS提供的工具生成一个新的MD5哈希。你可以临时在一个PHP环境中运行echo md5(你的新密码);或者使用在线MD5工具注意安全不要在公共电脑操作。假设新密码哈希是098f6bcd4621d373cade4e832627b4f6对应密码test管理员用户是admin更新语句为谨慎操作确保表前缀yourls_正确UPDATE yourls_options SET option_value a:1:{s:5:\admin\;s:32:\098f6bcd4621d373cade4e832627b4f6\;} WHERE option_name yourls_passwords;退出MySQL然后你就可以用新密码test登录了。5.3 插件安装与兼容性问题现象通过后台“插件管理”页面上传或安装插件后插件不生效、报错或导致后台白屏。原因与解决目录权限这是最常见的问题。容器内Apache/PHP通常以www-data用户运行。确保挂载的yourls_data卷对应的宿主机目录对Docker进程有足够的读写权限。使用命名卷通常能自动处理好权限问题。如果使用绑定挂载宿主目录可能需要调整目录所有者例如sudo chown -R 33:33 ./yourls_user_data33通常是www-data用户的UID。插件兼容性不是所有为传统部署方式编写的插件都能完美兼容容器化环境。特别是那些需要修改服务器配置如Apache的.htaccess之外的配置或依赖特定系统二进制文件的插件。调试模式在排查插件问题时可以临时在环境变量中设置YOURLS_DEBUG: true然后重启容器。这样页面底部会显示错误信息有助于定位问题。查看PHP错误日志进入容器查看Apache/PHP日志docker-compose exec yourls tail -f /var/log/apache2/error.log。5.4 性能瓶颈分析与优化问题现象短链接访问或后台操作变慢。排查方向数据库连接确保YOURLS容器和数据库容器部署在同一台主机上并通过Docker网络通信避免网络延迟。检查数据库性能例如通过docker-compose exec db mysql -u root -p -e SHOW PROCESSLIST;查看是否有慢查询。PHP OpCache官方镜像默认应该启用了OPcache来缓存PHP字节码。你可以通过挂载自定义的php.ini配置文件来调整OpCache的大小等参数以适应你的使用频率。Apache配置默认的Apache MPM配置可能不适合高并发。对于容器环境可以考虑切换到mpm_event并调整MaxRequestWorkers等参数。这需要你创建一个自定义的Apache配置文件并挂载到容器中如示例中注释掉的部分。资源限制在docker-compose.yml中为服务设置CPU和内存限制防止某个容器耗尽主机资源。services: yourls: # ... 其他配置 ... deploy: # 注意在Compose v3中resources在deploy下 resources: limits: cpus: 1 memory: 512M reservations: cpus: 0.5 memory: 256M反向代理缓存对于公开的短链接跳转YOURLS_PRIVATE: false可以在前置的Nginx或Caddy中设置对/路径的缓存极大地减轻后端压力。因为短链接一旦创建其目标地址是固定的。容器化部署YOURLS将复杂的运维工作标准化、简单化。它把最好的实践封装在镜像里让我们能更专注于短链接服务本身的使用和业务逻辑。从单机测试到生产部署这套方案都提供了清晰的路径和可控的复杂度。