Spaces:
Runtime error
Runtime error
Upload 7 files
Browse files- Dockerfile +33 -0
- README.md +171 -10
- docker.service +22 -0
- entrypoint.sh +30 -0
- install.sh +261 -0
- journalctl3.py +31 -0
- systemctl3.py +0 -0
Dockerfile
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# 使用 Debian 13 作为基础镜像
|
| 2 |
+
FROM debian:13
|
| 3 |
+
|
| 4 |
+
# 默认环境变量
|
| 5 |
+
# 时区:TZ
|
| 6 |
+
# 语言:LANGUAGE
|
| 7 |
+
# 安装模式: INSTALL_MODE
|
| 8 |
+
# 版本:VERSION
|
| 9 |
+
# 安装目录: PANEL_BASE_DIR
|
| 10 |
+
# 面板端口: PANEL_PORT
|
| 11 |
+
# 安全入口: PANEL_ENTRANCE
|
| 12 |
+
# 面板用户: PANEL_USERNAME
|
| 13 |
+
# 面板密码: PANEL_PASSWORD
|
| 14 |
+
ENV TZ=Asia/Shanghai \
|
| 15 |
+
LANGUAGE=zh \
|
| 16 |
+
PANEL_BASE_DIR=/opt \
|
| 17 |
+
PANEL_PORT=9999 \
|
| 18 |
+
PANEL_ENTRANCE=entrance \
|
| 19 |
+
PANEL_USERNAME=1panel \
|
| 20 |
+
PANEL_PASSWORD=1panel_password
|
| 21 |
+
|
| 22 |
+
# 设置工作目录为/app
|
| 23 |
+
WORKDIR /app
|
| 24 |
+
|
| 25 |
+
# 复制必要的文件
|
| 26 |
+
COPY entrypoint.sh install.sh systemctl3.py journalctl3.py docker.service ./
|
| 27 |
+
|
| 28 |
+
# 设置文件权限
|
| 29 |
+
RUN chmod +x ./entrypoint.sh && \
|
| 30 |
+
chmod +x ./install.sh
|
| 31 |
+
|
| 32 |
+
# 启动
|
| 33 |
+
ENTRYPOINT ["/app/entrypoint.sh"]
|
README.md
CHANGED
|
@@ -1,10 +1,171 @@
|
|
| 1 |
-
--
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# docker-1panel-v2
|
| 2 |
+
|
| 3 |
+
在 Docker 容器中运行 1Panel V2(通过 DooD 方式),支持 OpenWRT/iStoreOS 环境。
|
| 4 |
+
|
| 5 |
+
## ⚙️ 工作原理
|
| 6 |
+
|
| 7 |
+
1. **模拟 systemctl**:在容器内部增加一个模拟的 systemctl 脚本,以模拟系统服务管理,满足 1Panel 对 systemctl 的依赖。
|
| 8 |
+
2. **魔改官方安装脚本**:对 1Panel 官方安装脚本进行修改,使其适应容器环境。
|
| 9 |
+
3. **DooD 模式 (Docker-out-of-Docker)**:通过将宿主机的 `/var/run/docker.sock` 挂载到容器内部,使容器内的 1Panel 能够直接访问和管理宿主机上的 Docker 守护进程及容器。
|
| 10 |
+
|
| 11 |
+
## ❤️ 特别感谢
|
| 12 |
+
|
| 13 |
+
- [dph5199278/docker-1panel](https://github.com/dph5199278/docker-1panel):提供了在 Docker 容器中运行 1Panel 的初步思路与安装方式。
|
| 14 |
+
- [Xeath/1panel-in-docker](https://github.com/Xeath/1panel-in-docker):提供了运行 1Panel V2 所需的 Docker 服务伪装脚本,解决了 1Panel 在容器中对 Docker 环境的依赖。
|
| 15 |
+
- [gdraheim/docker-systemctl-replacement](https://github.com/gdraheim/docker-systemctl-replacement):提供了在 Docker 容器内部使用 systemctl 模拟脚本的实现。
|
| 16 |
+
|
| 17 |
+
## 📝 环境变量
|
| 18 |
+
|
| 19 |
+
- `TZ`:时区(默认:`Asia/Shanghai`)
|
| 20 |
+
- `LANGUAGE`:面板语言(可选:`en`、`fa`、`pt-BR`、`ru`、`zh`,默认:`zh`)
|
| 21 |
+
- `INSTALL_MODE`:安装模式(可选:`stable`、`beta`、`dev`,默认:`stable`)
|
| 22 |
+
- `VERSION`:版本号(可手动指定特定版本号,默认:在线获取最新稳定版本)
|
| 23 |
+
- `PANEL_BASE_DIR`:安装目录(默认:`/opt`)
|
| 24 |
+
- `PANEL_PORT`:面板端口(默认:`9999`)
|
| 25 |
+
- `PANEL_ENTRANCE`:安全入口(默认:`entrance`)
|
| 26 |
+
- `PANEL_USERNAME`:面板用户(默认:`1panel`)
|
| 27 |
+
- `PANEL_PASSWORD`:面板密码(默认:`1panel_password`)
|
| 28 |
+
|
| 29 |
+
## 📂 挂载目录
|
| 30 |
+
|
| 31 |
+
- **Docker 进程套接字(不可修改)**
|
| 32 |
+
|
| 33 |
+
`/var/run/docker.sock:/var/run/docker.sock`
|
| 34 |
+
|
| 35 |
+
允许容器内的 1Panel 直接与宿主机的 Docker 守护进程通信,管理宿主机上的 Docker 容器。
|
| 36 |
+
|
| 37 |
+
- **1Panel 数据及应用安装目录(重要)**
|
| 38 |
+
|
| 39 |
+
`/path/to/your/data:/path/to/your/data`(示例,**请务必替换为您的实际路径**)
|
| 40 |
+
|
| 41 |
+
此目录用于持久化存储 1Panel 的配置、数据以及通过它安装的所有应用。
|
| 42 |
+
|
| 43 |
+
**为保证所有应用正常工作,宿主机路径和容器内路径必须保持一致**。原因是 1Panel 安装应用时,会基于容器内的路径(由 `PANEL_BASE_DIR` 定义)来为应用创建数据卷。如果内外路径不匹配,1Panel 本身可能正常运行,但其创建的应用将因找不到正确的数据目录而启动失败。
|
| 44 |
+
|
| 45 |
+
您可以选择直接挂载 `PANEL_BASE_DIR` 指定的目录,或其任何一级父目录,前提是 -v 参数冒号前后的路径必须完全相同**。例如,如果 `PANEL_BASE_DIR` 是 `/path/to/your/data`,那么 `-v /path/to/your/data:/path/to/your/data` 和 `-v /path:/path` 都是有效的配置。
|
| 46 |
+
|
| 47 |
+
## 🐳 部署方式
|
| 48 |
+
|
| 49 |
+
### Docker CLI 部署示例
|
| 50 |
+
|
| 51 |
+
1. **准备 Docker 镜像**
|
| 52 |
+
|
| 53 |
+
您可以使用 GitHub Container Registry 上的最新版预构建 Docker 镜像:`ghcr.io/purainity/docker-1panel-v2:latest`,也可以在本地构建镜像。
|
| 54 |
+
|
| 55 |
+
如需在本地构建 Docker 镜像,请将本仓库中的所有文件复制到同一目录下,`cd` 进入该目录后执行以下命令。您可以根据需要修改镜像名 `docker-1panel-v2`。
|
| 56 |
+
|
| 57 |
+
```bash
|
| 58 |
+
docker build -t docker-1panel-v2 .
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
2. **运行 Docker 容器**
|
| 62 |
+
|
| 63 |
+
使用以下命令运行 1Panel 容器。**请务必根据您的实际需求修改配置参数**。以下示例使用 ghcr 上的最新预构建镜像,容器名称为 `1panel`,1Panel 数据目录为 `/path/to/your/data`,面板端口 `9999`,安全入口 `entrance`,面板用户 `1panel`,面板密码 `1panel_password`,并自动下载最新稳定版。
|
| 64 |
+
|
| 65 |
+
使用 `--network host` 可以避免额外的端口映射配置,使 1Panel 直接监听宿主机的端口。
|
| 66 |
+
|
| 67 |
+
使用 `--restart unless-stopped` 可以使 1Panel 容器在异常退出时自动重启。
|
| 68 |
+
|
| 69 |
+
```bash
|
| 70 |
+
docker run -d \
|
| 71 |
+
--name 1panel \
|
| 72 |
+
--network host \
|
| 73 |
+
--restart unless-stopped \
|
| 74 |
+
-v /var/run/docker.sock:/var/run/docker.sock \
|
| 75 |
+
-v /path/to/your/data:/path/to/your/data \
|
| 76 |
+
-e PANEL_BASE_DIR=/path/to/your/data \
|
| 77 |
+
-e PANEL_PORT=9999 \
|
| 78 |
+
-e PANEL_ENTRANCE=entrance \
|
| 79 |
+
-e PANEL_USERNAME=1panel \
|
| 80 |
+
-e PANEL_PASSWORD=1panel_password \
|
| 81 |
+
ghcr.io/purainity/docker-1panel-v2:latest
|
| 82 |
+
```
|
| 83 |
+
|
| 84 |
+
3. **访问 1Panel**
|
| 85 |
+
|
| 86 |
+
1Panel 安装完成后,您可以通过 `http://您的宿主机IP:面板端口/安全入口` 访问 1Panel 面板,并使用您在环境变量中设置的用户和密码登录。
|
| 87 |
+
|
| 88 |
+
### Docker Compose 部署示例
|
| 89 |
+
|
| 90 |
+
1. **创建 `docker-compose.yml` 文件**
|
| 91 |
+
|
| 92 |
+
在项目根目录下创建一个名为 `docker-compose.yml` 的文件,内容如下。**请务必根据您的实际需求修改配置参数**。
|
| 93 |
+
|
| 94 |
+
```yaml
|
| 95 |
+
version: '3.8'
|
| 96 |
+
|
| 97 |
+
services:
|
| 98 |
+
1panel:
|
| 99 |
+
# 如果使用 ghcr 上的最新版预构建镜像
|
| 100 |
+
image: ghcr.io/purainity/docker-1panel-v2:latest
|
| 101 |
+
# 如果使用当前目录的 Dockerfile 本地构建镜像,请取消注释下一行,并注释上一行
|
| 102 |
+
# build: .
|
| 103 |
+
container_name: 1panel # 容器名称
|
| 104 |
+
network_mode: host # 使用宿主机网络
|
| 105 |
+
volumes:
|
| 106 |
+
- /var/run/docker.sock:/var/run/docker.sock # 挂载 Docker 套接字
|
| 107 |
+
- /path/to/your/data:/path/to/your/data # 挂载 1Panel 数据目录,请确保宿主机路径和容器内路径一致
|
| 108 |
+
environment:
|
| 109 |
+
TZ: Asia/Shanghai # 时区
|
| 110 |
+
LANGUAGE: zh # 面板语言
|
| 111 |
+
PANEL_BASE_DIR: /path/to/your/data # 安装目录
|
| 112 |
+
PANEL_PORT: 9999 # 面板端口
|
| 113 |
+
PANEL_ENTRANCE: entrance # 安全入口
|
| 114 |
+
PANEL_USERNAME: 1panel # 面板用户
|
| 115 |
+
PANEL_PASSWORD: 1panel_password # 面板密码
|
| 116 |
+
restart: unless-stopped # 容器退出时自动重启,除非手动停止
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
2. **部署服务**
|
| 120 |
+
|
| 121 |
+
在 `docker-compose.yml` 文件所在的目录下,执行以下命令构建镜像并启动服务。
|
| 122 |
+
|
| 123 |
+
```bash
|
| 124 |
+
docker compose up -d --build
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
(如果您的系统使用的是旧版 docker-compose,请使用 `docker-compose up -d --build`)
|
| 128 |
+
|
| 129 |
+
3. **访问 1Panel**
|
| 130 |
+
|
| 131 |
+
1Panel 安装完成后,您可以通过 `http://您的宿主机IP:面板端口/安全入口` 访问 1Panel 面板,并使用您在环境变量中设置的用户和密码登录。
|
| 132 |
+
|
| 133 |
+
## ❓ 常见问题
|
| 134 |
+
|
| 135 |
+
1. **运行容器后无法进入网页面板?**
|
| 136 |
+
|
| 137 |
+
请使用以下命令查看容器日志,注意将容器名 `1panel` 修改为您的实际容器名称。
|
| 138 |
+
|
| 139 |
+
```bash
|
| 140 |
+
docker logs -f 1panel
|
| 141 |
+
```
|
| 142 |
+
|
| 143 |
+
如果日志中未出现 `[INFO] listen at http://0.0.0.0:面板端口 [tcp4]`,则说明 1Panel 还未启动,请耐心等待。如果重启容器后仍无法访问,请检查是否使用了 `host` 网络模式,若否,请检查是否正确配置了端口映射。
|
| 144 |
+
|
| 145 |
+
2. **网页面板出现 `请求错误,请检查该节点状态: stat /etc/1panel/agent.sock: no such file or directory` ?**
|
| 146 |
+
|
| 147 |
+
这是 `1panel-agent` 服务还未完全启动。请耐心等待几秒钟后刷新网页即可。若长时间这样,请尝试重启容器。
|
| 148 |
+
|
| 149 |
+
3. **1Panel 安装完成后,如何修改安全入口、面板用户、面板密码等设置?**
|
| 150 |
+
|
| 151 |
+
环境变量中的设置仅在首次安装 1Panel 时有效。如果需要在安装完成后修改这些设置,请通过 1Panel 的网页面板进行操作。
|
| 152 |
+
|
| 153 |
+
4. **如何更换 1Panel 版本?**
|
| 154 |
+
|
| 155 |
+
环境变量中的设置仅在首次安装 1Panel 时有效。对于常规升级,您可直接在 1Panel 的网页面板中进行在线更新。若需进行版本切换(如降级、或在 `stable` 与 `dev` 等通道间切换),则需要重建容器。请确保 1Panel 数据目录已正确持久化到宿主机,然后停止并删除旧容器,最后使用原部署命令,修改 `INSTALL_MODE` 或 `VERSION` 环境变量后重新创建容器。
|
| 156 |
+
|
| 157 |
+
5. **如何使用 1pctl 命令行操作?**
|
| 158 |
+
|
| 159 |
+
请先使用以下命令进入容器内部 Bash 终端,然后输入 `1pctl` 即可操作,注意将容器名 `1panel` 修改为您的实际容器名称。
|
| 160 |
+
|
| 161 |
+
```bash
|
| 162 |
+
docker exec -it 1panel bash
|
| 163 |
+
```
|
| 164 |
+
|
| 165 |
+
6. **能否不设置安全入口?**
|
| 166 |
+
|
| 167 |
+
首次安装时必须设置安全入口。如果您想关闭安全入口,请在 1Panel 安装完成后,进入网页面板进行关闭操作。**请勿手动将 `PANEL_ENTRANCE` 环境变量设置为空字符串,这会导致安装完成后 1Panel 无法启动!**
|
| 168 |
+
|
| 169 |
+
7. **为什么不在镜像构建阶段就安装好 1Panel,而是在运行容器时才安装?这是否违背了 Docker 的不变性原则?**
|
| 170 |
+
|
| 171 |
+
1Panel 版本更新频繁,本项目旨在提供一个通用的容器化运行环境,而非固化特定版本。采用运行时安装的方式,可以避免频繁构建容器镜像,并允许用户通过 `INSTALL_MODE` 和 `VERSION` 环境变量灵活指定需要安装的 1Panel 版本。
|
docker.service
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[Unit]
|
| 2 |
+
Description=Docker Application Container Engine
|
| 3 |
+
Documentation=https://docs.docker.com
|
| 4 |
+
After=network.target
|
| 5 |
+
|
| 6 |
+
[Service]
|
| 7 |
+
Type=simple
|
| 8 |
+
# 当前服务只是为了让1panel可以识别docker启动,没有其他作用
|
| 9 |
+
ExecStart=/bin/sh -c \
|
| 10 |
+
'while true; do \
|
| 11 |
+
if [ ! -S /var/run/docker.sock ]; then \
|
| 12 |
+
systemctl --no-block fail docker-sock-monitor.service; \
|
| 13 |
+
exit 1; \
|
| 14 |
+
fi; \
|
| 15 |
+
sleep 10; \
|
| 16 |
+
done'
|
| 17 |
+
Restart=on-failure
|
| 18 |
+
RestartSec=5s
|
| 19 |
+
User=root
|
| 20 |
+
|
| 21 |
+
[Install]
|
| 22 |
+
WantedBy=multi-user.target
|
entrypoint.sh
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# 判断 1Panel-core 和 1Panel-agent 命令是否存在,如果任一不存在则执行安装脚本
|
| 4 |
+
if ! command -v 1panel-core &> /dev/null || ! command -v 1panel-agent &> /dev/null; then
|
| 5 |
+
echo "未检测到 1panel-core 或 1panel-agent,准备安装..."
|
| 6 |
+
bash /app/install.sh
|
| 7 |
+
else
|
| 8 |
+
echo "1Panel 已安装,正在启动。"
|
| 9 |
+
fi
|
| 10 |
+
|
| 11 |
+
# 1Panel数据初始化
|
| 12 |
+
systemctl start 1panel-core
|
| 13 |
+
sleep 3
|
| 14 |
+
systemctl stop 1panel-core
|
| 15 |
+
|
| 16 |
+
# 启动 docker
|
| 17 |
+
echo "Start Docker"
|
| 18 |
+
systemctl start docker
|
| 19 |
+
|
| 20 |
+
# 启动 1Panel
|
| 21 |
+
echo "Start 1Panel Core"
|
| 22 |
+
systemctl start 1panel-core
|
| 23 |
+
|
| 24 |
+
# 等待 1Panel Core 启动
|
| 25 |
+
sleep 3
|
| 26 |
+
echo "Start 1Panel Agent"
|
| 27 |
+
systemctl start 1panel-agent
|
| 28 |
+
|
| 29 |
+
# 监听日志
|
| 30 |
+
systemctl log 1panel-core -f
|
install.sh
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
# 失败退出
|
| 4 |
+
set -e
|
| 5 |
+
|
| 6 |
+
# 设置时区
|
| 7 |
+
echo -n "$TZ" > /etc/timezone
|
| 8 |
+
|
| 9 |
+
# 检查系统架构
|
| 10 |
+
echo "检查系统架构..."
|
| 11 |
+
os_check=$(uname -a)
|
| 12 |
+
arch=""
|
| 13 |
+
if [[ $os_check =~ 'x86_64' ]]; then
|
| 14 |
+
arch="amd64"
|
| 15 |
+
elif [[ $os_check =~ 'arm64' ]] || [[ $os_check =~ 'aarch64' ]]; then
|
| 16 |
+
arch="arm64"
|
| 17 |
+
elif [[ $os_check =~ 'armv7l' ]]; then
|
| 18 |
+
arch="armv7"
|
| 19 |
+
elif [[ $os_check =~ 'ppc64le' ]]; then
|
| 20 |
+
arch="ppc64le"
|
| 21 |
+
elif [[ $os_check =~ 's390x' ]]; then
|
| 22 |
+
arch="s390x"
|
| 23 |
+
elif [[ $os_check =~ 'riscv64' ]]; then
|
| 24 |
+
arch="riscv64"
|
| 25 |
+
else
|
| 26 |
+
echo "暂不支持的系统架构,请参阅官方文档,选择受支持的系统。"
|
| 27 |
+
exit 1
|
| 28 |
+
fi
|
| 29 |
+
echo "系统架构检测完成: ${arch}"
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
# 安装必要的软件包
|
| 33 |
+
echo "安装必要的软件包..."
|
| 34 |
+
apt-get update
|
| 35 |
+
DEBIAN_FRONTEND=noninteractive TZ="$TZ" apt-get install -y ca-certificates curl wget iproute2 tzdata python3 procps docker-cli docker-buildx docker-compose
|
| 36 |
+
|
| 37 |
+
# 创建 systemctl 模拟脚本
|
| 38 |
+
echo "正在创建 systemctl 模拟脚本..."
|
| 39 |
+
cp systemctl3.py /usr/bin/systemctl
|
| 40 |
+
chmod +x /usr/bin/systemctl
|
| 41 |
+
|
| 42 |
+
# 创建 journalctl 模拟脚本
|
| 43 |
+
echo "正在创建 journalctl 模拟脚本..."
|
| 44 |
+
cp journalctl3.py /usr/bin/journalctl
|
| 45 |
+
chmod +x /usr/bin/journalctl
|
| 46 |
+
|
| 47 |
+
# 创建 docker 伪装 systemctl 服务文件
|
| 48 |
+
echo "正在创建 docker 伪装 systemctl 服务文件..."
|
| 49 |
+
cp docker.service /usr/lib/systemd/system/
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
# 1Panel 安装主函数
|
| 53 |
+
main_install() {
|
| 54 |
+
# 获取当前脚本的目录
|
| 55 |
+
local current_dir=$(pwd)
|
| 56 |
+
|
| 57 |
+
# 语言文件配置
|
| 58 |
+
echo "$LANGUAGE" > "$current_dir/.selected_language" # 将选择的语言写入文件
|
| 59 |
+
local lang_file="$current_dir/lang/$LANGUAGE.sh"
|
| 60 |
+
if [ -f "$lang_file" ]; then
|
| 61 |
+
source "$lang_file" # 导入选定语言的文本变量
|
| 62 |
+
echo "已加载语言文件: $lang_file"
|
| 63 |
+
else
|
| 64 |
+
echo "错误: 语言文件 $lang_file 不存在。"
|
| 65 |
+
exit 1
|
| 66 |
+
fi
|
| 67 |
+
|
| 68 |
+
# 设置安装目录
|
| 69 |
+
local use_existing=false # 标记是否使用现有数据
|
| 70 |
+
# 验证 PANEL_BASE_DIR 是否为绝对路径
|
| 71 |
+
if [[ "$PANEL_BASE_DIR" != /* ]]; then
|
| 72 |
+
echo "错误: 安装目录 $PANEL_BASE_DIR 无效,请提供目录的完整路径。"
|
| 73 |
+
exit 1
|
| 74 |
+
fi
|
| 75 |
+
# 创建安装目录
|
| 76 |
+
mkdir -p "$PANEL_BASE_DIR"
|
| 77 |
+
# 检查安装目录下是否存在 1Panel 数据库文件
|
| 78 |
+
if [[ -f "$PANEL_BASE_DIR/1panel/db/core.db" ]]; then
|
| 79 |
+
use_existing=true
|
| 80 |
+
echo "检测到现有 1Panel 数据,将使用现有配置。"
|
| 81 |
+
fi
|
| 82 |
+
|
| 83 |
+
# 设置面板端口
|
| 84 |
+
# 验证端口号是否为数字且在合法范围内 (1-65535)
|
| 85 |
+
if ! [[ "$PANEL_PORT" =~ ^[1-9][0-9]{0,4}$ && "$PANEL_PORT" -le 65535 ]]; then
|
| 86 |
+
echo "错误: 面板端口 $PANEL_PORT 无效,输入的端口号必须在 1 到 65535 之间。"
|
| 87 |
+
exit 1
|
| 88 |
+
fi
|
| 89 |
+
# 检查端口是否被占用
|
| 90 |
+
if ss -tlun | grep -q ":$PANEL_PORT " >/dev/null 2>&1; then
|
| 91 |
+
echo "错误: 面板端口 $PANEL_PORT 已被占用。"
|
| 92 |
+
exit 1
|
| 93 |
+
fi
|
| 94 |
+
|
| 95 |
+
# 检测宿主机的 Docker Daemon 版本
|
| 96 |
+
local docker_version=$(docker --version | grep -oE '[0-9]+\.[0-9]+' | head -n 1)
|
| 97 |
+
local major_version=${docker_version%%.*}
|
| 98 |
+
if [[ $major_version -lt 20 ]]; then
|
| 99 |
+
echo "检测到宿主机 Docker Daemon 版本低于 20.x,建议手动升级以避免功能受限。"
|
| 100 |
+
fi
|
| 101 |
+
|
| 102 |
+
echo "正在配置 1Panel 服务..."
|
| 103 |
+
|
| 104 |
+
local run_base_dir="$PANEL_BASE_DIR/1panel" # 1Panel 实际运行目录
|
| 105 |
+
mkdir -p "$run_base_dir"
|
| 106 |
+
# 清理旧的 1Panel 运行目录内容,安全删除
|
| 107 |
+
rm -rf "$run_base_dir:?/*"
|
| 108 |
+
|
| 109 |
+
cd "${current_dir}" || exit # 切换到当前脚本目录
|
| 110 |
+
|
| 111 |
+
# 复制并设置 1panel-core 可执行文件
|
| 112 |
+
cp ./1panel-core /usr/local/bin && chmod +x /usr/local/bin/1panel-core
|
| 113 |
+
# 移除旧的软链接
|
| 114 |
+
if [[ -e /usr/bin/1panel ]]; then
|
| 115 |
+
rm -f /usr/bin/1panel
|
| 116 |
+
fi
|
| 117 |
+
# 兼容旧版,将 1panel-core 软链接到 1panel
|
| 118 |
+
ln -s /usr/local/bin/1panel-core /usr/bin/1panel >/dev/null 2>&1
|
| 119 |
+
# 确保 /usr/bin/1panel-core 存在软链接 (如果需要)
|
| 120 |
+
if [[ ! -f /usr/bin/1panel-core ]]; then
|
| 121 |
+
ln -s /usr/local/bin/1panel-core /usr/bin/1panel-core >/dev/null 2>&1
|
| 122 |
+
fi
|
| 123 |
+
|
| 124 |
+
# 复制并设置 1panel-agent 可执行文件
|
| 125 |
+
cp ./1panel-agent /usr/local/bin && chmod +x /usr/local/bin/1panel-agent
|
| 126 |
+
# 确保 /usr/bin/1panel-agent 存在软链接 (如果需要)
|
| 127 |
+
if [[ ! -f /usr/bin/1panel-agent ]]; then
|
| 128 |
+
ln -s /usr/local/bin/1panel-agent /usr/bin/1panel-agent >/dev/null 2>&1
|
| 129 |
+
fi
|
| 130 |
+
|
| 131 |
+
# 复制并配置 1pctl 控制工具
|
| 132 |
+
cp ./1pctl /usr/local/bin && chmod +x /usr/local/bin/1pctl
|
| 133 |
+
# 使用 sed 命令替换 1pctl 脚本中的配置变量
|
| 134 |
+
sed -i -e "s#BASE_DIR=.*#BASE_DIR=${PANEL_BASE_DIR}#g" /usr/local/bin/1pctl
|
| 135 |
+
sed -i -e "s#ORIGINAL_PORT=.*#ORIGINAL_PORT=${PANEL_PORT}#g" /usr/local/bin/1pctl
|
| 136 |
+
sed -i -e "s#ORIGINAL_USERNAME=.*#ORIGINAL_USERNAME=${PANEL_USERNAME}#g" /usr/local/bin/1pctl
|
| 137 |
+
# 密码中可能包含特殊字符,需要进行转义
|
| 138 |
+
local escaped_panel_password=$(echo "$PANEL_PASSWORD" | sed 's/[!@#$%*_,.?]/\\&/g')
|
| 139 |
+
sed -i -e "s#ORIGINAL_PASSWORD=.*#ORIGINAL_PASSWORD=${escaped_panel_password}#g" /usr/local/bin/1pctl
|
| 140 |
+
sed -i -e "s#ORIGINAL_ENTRANCE=.*#ORIGINAL_ENTRANCE=${PANEL_ENTRANCE}#g" /usr/local/bin/1pctl
|
| 141 |
+
sed -i -e "s#LANGUAGE=.*#LANGUAGE=${LANGUAGE}#g" /usr/local/bin/1pctl
|
| 142 |
+
# 如果是使用现有数据,则在 1pctl 中添加或修改 CHANGE_USER_INFO 标记
|
| 143 |
+
if [[ "$use_existing" == true ]]; then
|
| 144 |
+
if grep -q "^CHANGE_USER_INFO=" "/usr/local/bin/1pctl"; then
|
| 145 |
+
sed -i 's/^CHANGE_USER_INFO=.*/CHANGE_USER_INFO=use_existing/' "/usr/local/bin/1pctl"
|
| 146 |
+
else
|
| 147 |
+
sed -i '/^LANGUAGE=.*/a CHANGE_USER_INFO=use_existing' "/usr/local/bin/1pctl"
|
| 148 |
+
fi
|
| 149 |
+
fi
|
| 150 |
+
# 确保 /usr/bin/1pctl 存在软链接 (如果需要)
|
| 151 |
+
if [[ ! -f /usr/bin/1pctl ]]; then
|
| 152 |
+
ln -s /usr/local/bin/1pctl /usr/bin/1pctl >/dev/null 2>&1
|
| 153 |
+
fi
|
| 154 |
+
|
| 155 |
+
# 复制 GeoIP 数据
|
| 156 |
+
if [ -d "$run_base_dir/geo" ]; then
|
| 157 |
+
rm -rf "$run_base_dir/geo" # 清理旧的 GeoIP 目录
|
| 158 |
+
fi
|
| 159 |
+
mkdir -p "$run_base_dir/geo"
|
| 160 |
+
cp -r ./GeoIP.mmdb "$run_base_dir/geo/"
|
| 161 |
+
|
| 162 |
+
# 复制语言文件
|
| 163 |
+
cp -r ./lang /usr/local/bin
|
| 164 |
+
|
| 165 |
+
# 复制 systemd 服务文件
|
| 166 |
+
cp ./1panel-core.service /etc/systemd/system
|
| 167 |
+
cp ./1panel-agent.service /etc/systemd/system
|
| 168 |
+
|
| 169 |
+
systemctl enable 1panel-agent.service
|
| 170 |
+
systemctl enable 1panel-core.service
|
| 171 |
+
systemctl daemon-reload
|
| 172 |
+
|
| 173 |
+
# 清理安装包和解压后的文件
|
| 174 |
+
echo "清理安装文件..."
|
| 175 |
+
cd ..
|
| 176 |
+
rm -f "${package_file_name}"
|
| 177 |
+
rm -rf "1panel-${VERSION}-linux-${arch}"
|
| 178 |
+
|
| 179 |
+
echo
|
| 180 |
+
echo "感谢您的耐心等待,安装已完成。"
|
| 181 |
+
echo "面板端口: $PANEL_PORT"
|
| 182 |
+
echo "安全入口: $PANEL_ENTRANCE"
|
| 183 |
+
echo "面板用户: $PANEL_USERNAME"
|
| 184 |
+
echo "面板密码: $PANEL_PASSWORD"
|
| 185 |
+
echo "请确保 Docker 以 host 网络模式运行或已经配置端口映射 $PANEL_PORT。"
|
| 186 |
+
echo
|
| 187 |
+
}
|
| 188 |
+
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
# 设置安装模式
|
| 192 |
+
if [[ -z "${INSTALL_MODE}" ]]; then
|
| 193 |
+
echo "未手动指定安装模式,默认采用 stable。"
|
| 194 |
+
INSTALL_MODE="stable"
|
| 195 |
+
else
|
| 196 |
+
echo "已手动指定安装模式: ${INSTALL_MODE}。"
|
| 197 |
+
fi
|
| 198 |
+
|
| 199 |
+
# 获取最新版本号
|
| 200 |
+
if [[ -z "${VERSION}" ]]; then
|
| 201 |
+
echo "未手动指定版本号,在线获取最新版本..."
|
| 202 |
+
VERSION=$(curl -s https://resource.fit2cloud.com/1panel/package/v2/${INSTALL_MODE}/latest)
|
| 203 |
+
if [[ -z "${VERSION}" ]]; then
|
| 204 |
+
echo "错误: 获取最新版本失败,请稍候重试。"
|
| 205 |
+
exit 1
|
| 206 |
+
else
|
| 207 |
+
echo "最新版本: ${VERSION}。"
|
| 208 |
+
fi
|
| 209 |
+
else
|
| 210 |
+
echo "已手动指定版本号: ${VERSION}。"
|
| 211 |
+
fi
|
| 212 |
+
|
| 213 |
+
hash_file_url="https://resource.fit2cloud.com/1panel/package/v2/${INSTALL_MODE}/${VERSION}/release/checksums.txt"
|
| 214 |
+
package_file_name="1panel-${VERSION}-linux-${arch}.tar.gz"
|
| 215 |
+
package_download_url="https://resource.fit2cloud.com/1panel/package/v2/${INSTALL_MODE}/${VERSION}/release/${package_file_name}"
|
| 216 |
+
expected_hash=$(curl -s "$hash_file_url" | grep "$package_file_name" | awk '{print $1}')
|
| 217 |
+
|
| 218 |
+
# 检查安装包是否已存在且哈希值匹配
|
| 219 |
+
if [[ -f "${package_file_name}" ]]; then
|
| 220 |
+
if [[ -n "${expected_hash}" ]]; then
|
| 221 |
+
actual_hash=$(sha256sum "${package_file_name}" | awk '{print $1}')
|
| 222 |
+
if [[ "${expected_hash}" == "${actual_hash}" ]]; then
|
| 223 |
+
echo "安装包已存在且哈希值匹配,跳过下载。"
|
| 224 |
+
tar zxvf "${package_file_name}"
|
| 225 |
+
cd "1panel-${VERSION}-linux-${arch}" || { echo "错误: 无法进入安装目录。"; exit 1; }
|
| 226 |
+
main_install
|
| 227 |
+
exit 0 # 安装完成,退出脚本
|
| 228 |
+
else
|
| 229 |
+
echo "已存在安装包,但哈希值不一致,开始重新下载。"
|
| 230 |
+
rm -f "${package_file_name}"
|
| 231 |
+
fi
|
| 232 |
+
else
|
| 233 |
+
echo "无法获取安装包的哈希值,将重新下载安装包以确保完整性。"
|
| 234 |
+
rm -f "${package_file_name}"
|
| 235 |
+
fi
|
| 236 |
+
fi
|
| 237 |
+
|
| 238 |
+
# 下载安装包
|
| 239 |
+
echo "开始下载 1Panel ${VERSION} 版本在线安装包..."
|
| 240 |
+
echo "安装包下载地址: ${package_download_url}"
|
| 241 |
+
curl -Lk -o "${package_file_name}" "${package_download_url}"
|
| 242 |
+
if [[ ! -f "${package_file_name}" ]]; then
|
| 243 |
+
echo "错误: 下载安装包失败,请稍候重试。"
|
| 244 |
+
exit 1
|
| 245 |
+
fi
|
| 246 |
+
echo "安装包下载完成。"
|
| 247 |
+
|
| 248 |
+
# 解压安装包
|
| 249 |
+
echo "开始解压安装包..."
|
| 250 |
+
tar zxvf "${package_file_name}"
|
| 251 |
+
if [[ $? -ne 0 ]]; then
|
| 252 |
+
echo "错误: 解压安装包失败,请稍候重试。"
|
| 253 |
+
rm -f "${package_file_name}"
|
| 254 |
+
exit 1
|
| 255 |
+
fi
|
| 256 |
+
echo "安装包解压完成。"
|
| 257 |
+
|
| 258 |
+
# 进入解压后的目录并执行安装脚本
|
| 259 |
+
echo "开始安装 1Panel..."
|
| 260 |
+
cd "1panel-${VERSION}-linux-${arch}" || { echo "错误: 无法进入安装目录。"; exit 1; }
|
| 261 |
+
main_install
|
journalctl3.py
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#! /usr/bin/python3
|
| 2 |
+
|
| 3 |
+
import argparse
|
| 4 |
+
import os
|
| 5 |
+
import sys
|
| 6 |
+
|
| 7 |
+
parser = argparse.ArgumentParser()
|
| 8 |
+
parser.add_argument('-u', '--unit', metavar='unit', type=str, required=True, help='Systemd unit to display')
|
| 9 |
+
parser.add_argument('-f', '--follow', default=False, action='store_true', help='Follows the log')
|
| 10 |
+
parser.add_argument('-n', '--lines', metavar='num', type=int, help='Num of lines to display')
|
| 11 |
+
parser.add_argument('--no-pager', default=False, action='store_true', help='Do not pipe through a pager')
|
| 12 |
+
parser.add_argument('--system', default=False, action='store_true', help='Show system units')
|
| 13 |
+
parser.add_argument('--user', default=False, action='store_true', help='Show user units')
|
| 14 |
+
parser.add_argument('--root', metavar='path', type=str, help='Use subdirectory path')
|
| 15 |
+
parser.add_argument('-x', default=False, action='store_true', help='Switch on verbose mode')
|
| 16 |
+
args = parser.parse_args()
|
| 17 |
+
|
| 18 |
+
systemctl_py = "systemctl3.py"
|
| 19 |
+
path = os.path.dirname(sys.argv[0])
|
| 20 |
+
systemctl = os.path.join(path, systemctl_py)
|
| 21 |
+
|
| 22 |
+
cmd = [ systemctl, "log", args.unit ] # drops the -u
|
| 23 |
+
if args.follow: cmd += [ "-f" ]
|
| 24 |
+
if args.lines: cmd += [ "-n", str(args.lines) ]
|
| 25 |
+
if args.no_pager: cmd += [ "--no-pager" ]
|
| 26 |
+
if args.system: cmd += [ "--system" ]
|
| 27 |
+
elif args.user: cmd += [ "--user" ]
|
| 28 |
+
if args.root: cmd += [ "--root", start(args.root) ]
|
| 29 |
+
if args.x: cmd += [ "-vvv" ]
|
| 30 |
+
|
| 31 |
+
os.execvp(cmd[0], cmd)
|
systemctl3.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|