使用 Coolify 极简运维你的项目和数据库
使用 Coolify 极简运维你的项目和数据库2025年3月8日更新coolify现在变得很复杂,建议用dpanel 引言本文将介绍一个名为 Coolify 的开源软件,基于 Docker 提供了托管网站、数据库等服务的功能,功能丰富强大,操作简单。官方自称是Heroku / Netlify / Vercel 的开源替代。 我在试用了以后立即决定抛弃之前 nginx proxy manager + docker-compose 的运维方案,全面拥抱 Coolify,因为它真是太好用了。 安装官网提供了一个简单的安装命令,将自动安装 docker 和 Coolify 的几个必备容器。包括下图中的容器。其中 Traefik 是整个系统的 http 和 https 网关,coolify-server 是软件主体,redis、postgres、soketi 是 coolify 的依赖项。 安装完成后会提示你去访问服务器的 8000 端口,这是 coolify 的 http 端口,我们可以暂时使用它来进行一些基本配置。之后我们会使用 https 去访问它。 配置网关我...
告别笨重的 ELK,试试用 Loki 处理日志吧!
告别笨重的 ELK,试试用 Loki 处理日志吧!日志领域主流解决方案是 elk,但是这一套部署复杂、资源占用高,不适合个人开发者使用,如果你需要一个比命令行漂亮一些的日志查看工具,loki 就非常合适了。 promtail从 k8s/docker 中收集容器标准输出日志,发送到 loki 存储,grafana 在网页端对日志进行搜索和展示。非常轻量级,200MB 左右的内存就可以搞定。 安装首先在一个安装了 docker 的服务器部署 loki、grafana 和收集本机 docker 容器日志的promtail: 12345678910111213141516171819202122232425262728293031323334353637383940414243version: '3'services: grafana: image: grafana/grafana-enterprise container_name: grafana restart: unless-stopped networks: - ...
使用 VueGraggablePlus 实现 el-table 等第三方组件的拖拽排序
使用 VueGraggablePlus 实现 el-table 等第三方组件的拖拽排序引言当我们有一些表格数据需要可以调整顺序时,最直观的做法是拖拽(正如大部分 APP 的做法一样)。 我主要使用 vue3 + element plus 进行开发,当遇到这个需求时网上最常见的解决方案是 vue draggable,可惜这个项目已经 3 年没更新了,而另一个实现了类似功能并且还在积极更新的项目是 vue-draggable-plus,用法非常简单,而且可以很简单地支持第三方组件(例如 el-table)的拖拽排序。 可惜网上对于这个库的介绍非常有限,大多数就是照抄本就简略的官方文档。本文将介绍它在实际开发中的使用方法,帮助有类似需求的朋友节省时间。 演示安装:npm install vue-draggable-plus 以下代码写了一个表格,并将其用VueDraggable包裹起来以实现拖拽排序。并且在下方展示了数据的真实顺序。 1234567891011121314151617181920212223242526272829303132<template> <...
登录验证码发送间隔限制的设计与实现
登录验证码发送间隔限制的设计与实现引言在小项目设计登录模块时,一个常见的思路是账号与邮箱/手机号绑定,通过邮件/短信验证码的方式登录/注册。相比于传统的口令式注册/登录有以下优点: 用户不需要记住密码:只要邮箱/手机号还能用,就可以登录。 系统不需要考虑太多安全问题:数据库不存储敏感信息,安全性由邮箱/电信运营商保障。 登录、注册合一:简化开发。 发送邮件/短信验证码一般都要通过云厂商的服务来实现,如果有人恶意刷接口就会产生大量费用。而且登录验证码本身也是一段时间内有效的,不需要频繁调用。所以我们需要对发送验证码的接口做调用时间间隔的限制。 本文用 vue3 + element plus + springboot 的技术栈举例。重点在分享思路,在使用其他技术栈的情况下也可以套用。 后端目的:对于同一个邮箱来说,一分钟内最多发送一次验证码。 思路:使用 Caffeine 库的 Cache 类,过期策略是写后 1 分钟过期。key 存放邮箱,value 存一个 new Object()(我们可以称之为 time...
马督工自媒体课程学习笔记
马督工自媒体课程学习笔记这篇笔记整理的是我在看马督工自媒体课程时记下的一些方法论。它不只是关于“怎么做内容”,更像是在讨论:一个普通人如果想持续、严肃地观察现实,并把自己的观察讲清楚,应该建立怎样的思维框架。 课程里有些内容偏原则,有些内容偏实操。我先把自己觉得最有价值、也最容易迁移到写作和表达中的部分梳理出来,方便后面反复回看。 学这门课,到底是为了什么?对我来说,核心目的有两个: 更理性、更深刻地理解新闻与现实世界; 提升自己的表达能力,让输出的内容更有逻辑、更有说服力。 如果把“做内容”理解成一种长期训练,那么它训练的不只是写稿能力,更是观察世界、提炼问题和组织观点的能力。 我理解的几个核心原则1. 适度自信:不必是专家,但不能毫无准备媒体人在大多数专业领域里并不是专家,这很正常。关键不在于把自己伪装成无所不知的人,而在于承认自己的边界,同时快速补齐完成一次科普或评论所需的知识。 换句话说,不需要达到学术专家的深度,但至少要达到“足以对普通观众讲明白”的程度。很多时候,这种能力并不神秘,更像是一种高强度、目标明确的短期学习,甚至有点像大学期末突击:带着问题去学,只抓最关...
使用 k8s 搭建一个小巧但健全的 cicd 系统
使用 k8s 搭建一个小巧但健全的 cicd 系统引言本文将以作者的个人小项目“易导游”(e-tour) 为例,介绍作者目前正在使用的 cicd 方案。实现了自动更新部署、自动资源调度、日志系统、告警系统等功能。 总览 架构图如上,我们简单介绍一下图中的关键组件: git 仓库:使用 github 私有仓库,利用 github action 实现 push 后自动构建镜像并更新部署的功能 前端:以静态网页的形式托管在阿里云 oss 上。以节省服务器带宽和流量资源。 镜像仓库:在 infra 服务器自建私有镜像仓库。 k8s:主要目的是充分利用多台低配服务器的内存资源。 后端:以容器的形式运行在 k8s 集群中。 中间件:由于 k8s 并不适合运行有状态应用,所以像数据库、loki 这种中间件我放在一台内存足够大的安装了 docker 的服务器上(下文称之为 infra服务器) 监控告警: 优秀国产开源项目 hertzbeat,当检测到服务下线后通过飞书机器人告警。 日志:loki + promtail + grafana 可以查看 k8s 和 infra 中所有容器的标准输出日...
Docker 健康检查的目的、影响和处理
前言网上关于 Docker 的教程往往只会讲容器、镜像、网络、数据卷。对于健康检查往往只是一笔带过:在 Dockerfile 中写一个 HEALTHCHECK 命令,然后看到容器状态变成了 “healthy” 就万事大吉。而对于不健康的容器会造成什么影响、如何处理不健康的容器则很少提及。 如果想充分发挥容器化的健壮性优势,我们就需要认真审视 Docker 提供的健康检查功能。 结论先行Docker 健康检查是保障容器化应用可靠性的关键机制。 不健康的容器会被 Docker 网络自动隔离,但 Docker 本身不会重启它们。我们需要结合 autoheal 工具实现自动重启,并通过 Prometheus + Alertmanager 实现告警监控。 为什么需要健康检查?默认检查方式的局限性默认情况下,Docker 判断一个容器是否存活的方式是通过检测容器内 PID = 1 的进程是否存活(这个进程就是 Dockerfile 的 ENTRYPOINT 中启动的进程)。 这个检查方式非常粗放,因为有时容器已经失去了正常对外提供服务的能力,但是进程仍然存活。例如: 应用陷入死锁...
安全地远程调用Docker API
安全地远程调用Docker API引言你也许知道如何在一台安装了 docker 的机器上创建、停止、删除容器。但是如果发号施令的程序和 docker 不在同一台机器上该怎么办? 本文将介绍如何开启 docker api 远程调用、使用 http api 或者 java sdk 操作另一台机器上的 docker、以及如何确保 docker api 不被他人调用。 开启 docker api 远程调用(简单,不鉴权,快速体验)默认 docker 只允许本机使用docker命令进行操作,我们现在来开启 http api 调用,使得其他机器可以通过 http 请求来操作 docker。 注意:这种方法不对调用者权限进行校验,也就是说互联网上任何一个人都可以控制你的 docker。我们这里为了快速体验临时使用这种方法,长期使用请务必使用 tls 来鉴权,具体方法下文会介绍。 vim /lib/systemd/system/docker.service 编辑 docker 启动命令,找到 service 模块下的 ExecStart=xxx 这一行,在其末尾添加`-H=tc...
轻松配置 https:Let‘s Encrypt 介绍及 Nginx Proxy Manager 实用操作教程
轻松配置 https:Let‘s Encrypt 介绍及 Nginx Proxy Manager 实用操作教程前言一般我们在本地进行 web 开发时用的都是 http 协议,而部署到服务器上之后为了安全都要配置 https,以保证客户端和服务器之间的通信内容得到加密,不会被泄露或篡改。 本文将介绍 https 协议的基本知识(如果有基础可以跳过),以及如何使用 Let’s Encrypt 给你的服务优雅地配置 https。 HTTPShttps本质上还是http,只不过https使用了ssl协议来加密通信内容。 ssl是一个介于TCP和应用层的协议,基于非对称加密算法,用于确保通信双方的交流是私密的 对称加密加密解密使用同一把密钥,但是如何安全地传输这个密钥是个问题 非对称加密有三条原则: 私钥加密,公钥解密 公钥加密,私钥解密 公钥加密,公钥无法解密 服务端给客户端发放公钥,客户端使用公钥加密请求,只有服务端的私钥能解密。服务端使用私钥加密响应,客户端使用公钥解密。 看起来很美好,但这样存在很一个很大的问题:如果有一个坏人(中间人)像下图这样操作,你们的通讯还是会被窃听甚至...
ThreadLocal 内存泄漏问题
前言ThreadLocal 是 Java 中常见的线程隔离工具,但使用不当容易引发内存泄漏。这是一道经典的面试题,涉及 GC、引用类型、线程池等核心知识点。 结论先行使用不当可能导致内存泄漏,但只要及时调用 remove() 就可以避免。 ThreadLocal 的工作原理数据存储结构每个 Thread 对象都有一个类似哈希表的属性 threadLocals,用于存储该线程的私有变量。虽然这个哈希表的 Entry 结构与 HashMap 不同,但可以用哈希表的思想来理解: Key:ThreadLocal 对象的弱引用 Value:实际存储的数据 这样设计的好处是,同一个 ThreadLocal 对象在不同线程的 threadLocals 中对应不同的 value,从而实现了数据隔离。 为什么 Key 使用弱引用?这里最关键的设计是:为什么 Key 是弱引用,而不是 ThreadLocal 对象本身? 考虑这样的场景: 在 Web 服务器中,处理请求的线程通常是池化的,生命周期很长。如果不断有新的 ThreadLocal 对象被添加到线程的 threadLocals 中,而且...














