初始化
This commit is contained in:
1 parent
34474bd5fc
commit
b638b541d0
3008 files changed
+837699
No files matched your search
@@ -0,0 +1,7 @@
|
||||
.git
|
||||
.gitignore
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.sha256
|
||||
README*.md
|
||||
DEPLOY*.md
|
||||
@@ -0,0 +1,104 @@
|
||||
# Nginx 1.28 一键部署包
|
||||
|
||||
该目录用于在安装了 Docker 的 Linux 服务器上一键部署 Nginx 1.28。默认公网端口为 `80`,映射关系为 `80:80`,容器名为 `nginx-1.28`。
|
||||
|
||||
## 文件说明
|
||||
|
||||
- `Dockerfile`:以官方 `nginx:1.28` 为基础镜像构建本地镜像 `nginx-oneclick:1.28`。
|
||||
- `build-image.sh`:构建镜像并导出为 `nginx-oneclick-1.28.tar.gz`,用于离线分发。
|
||||
- `deploy.sh`:加载镜像包(或自动构建),创建/启动容器并进行 HTTP 验证。
|
||||
- `docker-compose.yml`:可选的 Compose 部署方式。
|
||||
- `nginx-oneclick-1.28.tar.gz`:如果随包提供,则优先离线加载,不需要访问 Docker Hub。
|
||||
|
||||
## 一键部署
|
||||
|
||||
将整个目录复制到目标服务器后执行:
|
||||
|
||||
```bash
|
||||
cd nginx-1.28-deployment
|
||||
chmod +x build-image.sh deploy.sh
|
||||
./deploy.sh
|
||||
```
|
||||
|
||||
部署脚本的行为是幂等的:
|
||||
|
||||
1. 如果目录中有镜像压缩包,优先执行 `docker load`。
|
||||
2. 没有镜像包但本机已有镜像时直接复用。
|
||||
3. 两者都没有时,以 `Dockerfile` 自动构建并拉取 `nginx:1.28` 基础镜像。
|
||||
4. 创建或启动 `nginx-1.28`,设置 `unless-stopped` 自动重启。
|
||||
5. 访问 `http://服务器公网IP/` 做 HTTP 检查。
|
||||
|
||||
## 构建并导出离线镜像
|
||||
|
||||
在可访问 Docker Hub 的 Docker 主机执行:
|
||||
|
||||
```bash
|
||||
./build-image.sh
|
||||
```
|
||||
|
||||
生成的 `nginx-oneclick-1.28.tar.gz` 和 `.sha256` 文件可以与脚本一起复制到无外网服务器。脚本会自动加载该镜像包。
|
||||
|
||||
本次服务器上的离线镜像包已生成在:
|
||||
|
||||
```text
|
||||
/opt/nginx-1.28-deployment/nginx-oneclick-1.28.tar.gz
|
||||
```
|
||||
|
||||
对应 SHA-256:`d322ba812dcd3e89fb8c0afd14f27e79e73432f7bc5a5a52324a0ca67e784014`。
|
||||
|
||||
## 端口和容器名
|
||||
|
||||
默认配置:
|
||||
|
||||
```text
|
||||
公网地址:http://服务器公网IP/
|
||||
主机端口:80
|
||||
容器端口:80
|
||||
容器名:nginx-1.28
|
||||
```
|
||||
|
||||
如 80 端口已被占用,可临时改用主机端口 8080:
|
||||
|
||||
```bash
|
||||
NGINX_HOST_PORT=8080 ./deploy.sh
|
||||
```
|
||||
|
||||
此时访问 `http://服务器公网IP:8080/`。如要更换容器名:
|
||||
|
||||
```bash
|
||||
NGINX_CONTAINER_NAME=nginx-prod ./deploy.sh
|
||||
```
|
||||
|
||||
## 已存在容器的处理
|
||||
|
||||
脚本不会默认删除或覆盖同名但配置不同的容器。确认要重建时显式执行:
|
||||
|
||||
```bash
|
||||
FORCE_RECREATE=1 ./deploy.sh
|
||||
```
|
||||
|
||||
该操作会删除并重新创建 `NGINX_CONTAINER_NAME` 指定的容器,不会删除镜像。
|
||||
|
||||
## Compose 部署(可选)
|
||||
|
||||
```bash
|
||||
docker compose up -d --build
|
||||
docker compose ps
|
||||
curl -I http://127.0.0.1/
|
||||
```
|
||||
|
||||
## 常用运维命令
|
||||
|
||||
```bash
|
||||
docker ps --filter name=nginx-1.28
|
||||
docker logs --tail 100 nginx-1.28
|
||||
docker exec nginx-1.28 nginx -v
|
||||
docker restart nginx-1.28
|
||||
docker stop nginx-1.28
|
||||
```
|
||||
|
||||
## 安全与公网访问检查
|
||||
|
||||
只映射 HTTP 端口时,服务器防火墙/云安全组需要允许 TCP `80`(或自定义的 `NGINX_HOST_PORT`)。部署脚本只负责 Docker 端口发布,不会修改云厂商安全组规则。
|
||||
|
||||
不要把 SSH 密码、私钥或生产配置写入该目录。若通过 SSH 远程部署,请使用密钥或交互式认证,并在密码已经暴露后及时轮换。
|
||||
@@ -0,0 +1,6 @@
|
||||
ARG NGINX_VERSION=1.28
|
||||
FROM nginx:${NGINX_VERSION}
|
||||
|
||||
LABEL org.opencontainers.image.title="Nginx 1.28 one-click deployment" \
|
||||
org.opencontainers.image.description="Reusable Nginx 1.28 deployment image" \
|
||||
org.opencontainers.image.version="1.28"
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
IMAGE="${NGINX_IMAGE:-nginx-oneclick:1.28}"
|
||||
NGINX_VERSION="${NGINX_VERSION:-1.28}"
|
||||
ARCHIVE="${NGINX_IMAGE_ARCHIVE:-${SCRIPT_DIR}/nginx-oneclick-1.28.tar.gz}"
|
||||
|
||||
command -v docker >/dev/null 2>&1 || {
|
||||
echo "错误:未找到 Docker,请先安装 Docker。" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
echo "[1/2] 构建镜像 ${IMAGE}(基础镜像 nginx:${NGINX_VERSION})"
|
||||
docker build \
|
||||
--pull \
|
||||
--build-arg "NGINX_VERSION=${NGINX_VERSION}" \
|
||||
--tag "${IMAGE}" \
|
||||
"${SCRIPT_DIR}"
|
||||
|
||||
echo "[2/2] 导出镜像 ${ARCHIVE}"
|
||||
mkdir -p "$(dirname -- "${ARCHIVE}")"
|
||||
tmp_archive="${ARCHIVE}.tmp"
|
||||
trap 'rm -f -- "${tmp_archive}"' EXIT
|
||||
docker save "${IMAGE}" | gzip -c >"${tmp_archive}"
|
||||
mv -f -- "${tmp_archive}" "${ARCHIVE}"
|
||||
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
sha256sum "${ARCHIVE}" >"${ARCHIVE}.sha256"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "构建完成:"
|
||||
echo " 镜像:${IMAGE}"
|
||||
echo " 文件:${ARCHIVE}"
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
IMAGE="${NGINX_IMAGE:-nginx-oneclick:1.28}"
|
||||
NGINX_VERSION="${NGINX_VERSION:-1.28}"
|
||||
CONTAINER_NAME="${NGINX_CONTAINER_NAME:-nginx-1.28}"
|
||||
HOST_PORT="${NGINX_HOST_PORT:-80}"
|
||||
CONTAINER_PORT=80
|
||||
FORCE_RECREATE="${FORCE_RECREATE:-0}"
|
||||
ARCHIVE="${NGINX_IMAGE_ARCHIVE:-${SCRIPT_DIR}/nginx-oneclick-1.28.tar.gz}"
|
||||
|
||||
die() {
|
||||
echo "错误:$*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
command -v docker >/dev/null 2>&1 || die "未找到 Docker,请先安装 Docker。"
|
||||
[[ "${HOST_PORT}" =~ ^[0-9]+$ ]] || die "NGINX_HOST_PORT 必须是数字。"
|
||||
(( HOST_PORT >= 1 && HOST_PORT <= 65535 )) || die "NGINX_HOST_PORT 必须在 1-65535 范围内。"
|
||||
|
||||
echo "部署参数:"
|
||||
echo " 镜像:${IMAGE}"
|
||||
echo " 容器:${CONTAINER_NAME}"
|
||||
echo " 端口:${HOST_PORT}:${CONTAINER_PORT}"
|
||||
|
||||
if ! docker image inspect "${IMAGE}" >/dev/null 2>&1 && [[ -f "${ARCHIVE}" ]]; then
|
||||
echo "[1/4] 从镜像包加载 ${ARCHIVE}"
|
||||
case "${ARCHIVE}" in
|
||||
*.tar.gz|*.tgz) gzip -cd -- "${ARCHIVE}" | docker load ;;
|
||||
*) docker load --input "${ARCHIVE}" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if ! docker image inspect "${IMAGE}" >/dev/null 2>&1; then
|
||||
echo "[1/4] 未找到本地镜像,自动构建 ${IMAGE}"
|
||||
docker build \
|
||||
--pull \
|
||||
--build-arg "NGINX_VERSION=${NGINX_VERSION}" \
|
||||
--tag "${IMAGE}" \
|
||||
"${SCRIPT_DIR}"
|
||||
else
|
||||
echo "[1/4] 已找到镜像 ${IMAGE}"
|
||||
fi
|
||||
|
||||
existing_container=0
|
||||
if docker container inspect "${CONTAINER_NAME}" >/dev/null 2>&1; then
|
||||
existing_container=1
|
||||
current_image="$(docker inspect -f '{{.Config.Image}}' "${CONTAINER_NAME}")"
|
||||
current_host_port="$(docker inspect -f '{{with (index .HostConfig.PortBindings "80/tcp")}}{{(index . 0).HostPort}}{{end}}' "${CONTAINER_NAME}" 2>/dev/null || true)"
|
||||
|
||||
if [[ "${current_image}" != "${IMAGE}" || "${current_host_port}" != "${HOST_PORT}" ]]; then
|
||||
if [[ "${FORCE_RECREATE}" != "1" ]]; then
|
||||
die "已存在同名容器但镜像或端口不匹配。确认后可设置 FORCE_RECREATE=1 再执行。"
|
||||
fi
|
||||
echo "[2/4] FORCE_RECREATE=1,重建已有容器 ${CONTAINER_NAME}"
|
||||
docker rm -f "${CONTAINER_NAME}" >/dev/null
|
||||
existing_container=0
|
||||
fi
|
||||
fi
|
||||
|
||||
if (( existing_container == 0 )); then
|
||||
echo "[2/4] 创建容器 ${CONTAINER_NAME}"
|
||||
docker run -d \
|
||||
--name "${CONTAINER_NAME}" \
|
||||
--restart unless-stopped \
|
||||
--publish "${HOST_PORT}:${CONTAINER_PORT}" \
|
||||
--log-opt max-size=10m \
|
||||
--log-opt max-file=3 \
|
||||
"${IMAGE}" >/dev/null
|
||||
else
|
||||
running="$(docker inspect -f '{{.State.Running}}' "${CONTAINER_NAME}")"
|
||||
if [[ "${running}" != "true" ]]; then
|
||||
echo "[2/4] 启动已存在的容器 ${CONTAINER_NAME}"
|
||||
docker start "${CONTAINER_NAME}" >/dev/null
|
||||
else
|
||||
echo "[2/4] 容器 ${CONTAINER_NAME} 已在运行"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "[3/4] 等待容器就绪"
|
||||
for _ in {1..30}; do
|
||||
running="$(docker inspect -f '{{.State.Running}}' "${CONTAINER_NAME}" 2>/dev/null || true)"
|
||||
[[ "${running}" == "true" ]] && break
|
||||
sleep 1
|
||||
done
|
||||
[[ "${running}" == "true" ]] || die "容器未能进入运行状态。"
|
||||
|
||||
echo "[4/4] 验证 HTTP 服务"
|
||||
url="http://127.0.0.1:${HOST_PORT}/"
|
||||
http_ok=0
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
for _ in {1..30}; do
|
||||
if curl --fail --silent --max-time 2 "${url}" >/dev/null; then
|
||||
http_ok=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
elif command -v wget >/dev/null 2>&1; then
|
||||
for _ in {1..30}; do
|
||||
if wget -q -O /dev/null --timeout=2 "${url}"; then
|
||||
http_ok=1
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
else
|
||||
echo "警告:系统没有 curl 或 wget,跳过 HTTP 验证。" >&2
|
||||
http_ok=1
|
||||
fi
|
||||
(( http_ok == 1 )) || die "HTTP 验证失败:${url}"
|
||||
|
||||
nginx_version="$(docker exec "${CONTAINER_NAME}" nginx -v 2>&1 || true)"
|
||||
echo
|
||||
echo "部署成功。"
|
||||
echo " 容器:${CONTAINER_NAME}"
|
||||
echo " 端口:0.0.0.0:${HOST_PORT} -> ${CONTAINER_PORT}"
|
||||
echo " 版本:${nginx_version}"
|
||||
echo " 查看状态:docker ps --filter name=${CONTAINER_NAME}"
|
||||
@@ -0,0 +1,11 @@
|
||||
services:
|
||||
nginx:
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
NGINX_VERSION: "${NGINX_VERSION:-1.28}"
|
||||
image: "${NGINX_IMAGE:-nginx-oneclick:1.28}"
|
||||
container_name: "${NGINX_CONTAINER_NAME:-nginx-1.28}"
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "${NGINX_HOST_PORT:-80}:80"
|
||||
@@ -0,0 +1 @@
|
||||
d322ba812dcd3e89fb8c0afd14f27e79e73432f7bc5a5a52324a0ca67e784014 nginx-oneclick-1.28.tar.gz
|
||||
Reference in new issue
Block a user