Docker安装alpine容器并部署LNMP环境

宿主机Red Hat系

更新系统并安装自动补齐增强包:

dnf update && dnf install -y bash-completion kernel-modules-extra iptables-nft

立即刷新当前终端环境使其生效

source /etc/profile.d/bash_completion.sh

重启系统

reboot

添加docker源

dnf install -y dnf-plugins-core
dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装并启动基础服务

dnf install -y firewalld docker-ce docker-ce-cli containerd.io

限制 Docker 日志大小(防止撑爆硬盘)

mkdir -p /etc/docker && cat> /etc/docker/daemon.json <<EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF
# 重新启动daemon:
systemctl daemon-reload

启动并启用防火墙…

systemctl start firewalld   #开启
systemctl status firewalld  # 开启状态
systemctl enable firewalld  # 设置开机自启

宿主机对外端口与 NAT 网络配置

# 开启常用端口
firewall-cmd --permanent --zone=public --add-port=80/tcp
firewall-cmd --permanent --zone=public --add-port=443/tcp
# HTTP/3 / QUIC
firewall-cmd --permanent --zone=public --add-port=443/udp
firewall-cmd --permanent --zone=public --add-port=22/tcp
# 核心:允许公共区域的 IP 伪装(NAT转换),同时支持 IPv4 和 IPv6 容器访问外网
firewall-cmd --permanent --zone=public --add-masquerade
# 重载防火墙使规则生效..."
firewall-cmd --reload

开启内核 IP 转发(IPv4 + IPv6 双栈)

cat > /etc/sysctl.conf <<EOF
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.forwarding = 1
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr
EOF
sysctl -p && lsmod | grep bbr

启动 Docker。

systemctl start docker
# 查看运行状态
systemctl status docker
# 启动并设置开机自启
systemctl enable docker

下载 alpine 镜像

docker pull alpine:3.24

列出本地主机上的镜像

docker images

镜像名:标签 删除

docker rmi -f alpine:3.24

删除 容器

docker rm -f alpine

启动容器

docker run -itd \
  -p 80:80 \
  -p 443:443/tcp \
  -p 443:443/udp \
  -e TZ=Asia/Shanghai \
  --restart=always \
  --name alpine \
  alpine:3.24 /bin/sh

查看运行的容器

docker ps

进入容器

docker exec -it alpine /bin/sh

容器内安装依赖:

apk update && apk upgrade
apk add --no-cache \
build-base linux-headers perl autoconf automake libtool \
curl pcre-dev zlib-dev git wget mariadb mariadb-client \
php83 php83-fpm php83-mysqli php83-pdo_mysql php83-mbstring php83-json

验证时间

date

如果时间非CST作如下修改

#--------------------修复时间--------------------------------------
apk add --no-cache tzdata
# 1. 创建上海时区的软链接覆盖默认时区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

# 2. 刷新容器内的时区变量
echo "Asia/Shanghai" > /etc/timezone

# 4. 验证时间是否修改成功
date
#-----------------------------------------------------------------

下载geoip2数据库

cd /root && git clone https://github.com/leev/ngx_http_geoip2_module.git

下载libmaxminddb

wget -nc https://github.com/maxmind/libmaxminddb/releases/download/1.13.3/libmaxminddb-1.13.3.tar.gz && tar -zxvf libmaxminddb-1.13.3.tar.gz && cd libmaxminddb-1.13.3

编译libmaxminddb

./configure && make -j$(nproc) && make install && ldconfig

下载/安装/解压 openssl删除已使用文件

cd .. && wget -nc https://github.com/openssl/openssl/releases/download/openssl-4.0.1/openssl-4.0.1.tar.gz && tar -zxvf openssl-4.0.1.tar.gz && rm -rf libmaxminddb-1.13.3.tar.gz openssl-4.0.1.tar.gz

下载/解压 nginx:

wget -nc https://nginx.org/download/nginx-1.30.3.tar.gz && tar -zxvf nginx-1.30.3.tar.gz && cd nginx-1.30.3
添加编译插件:
./configure \
  --prefix=/usr/local/nginx \
  --conf-path=/etc/nginx/nginx.conf \
  --pid-path=/var/run/nginx.pid \
  --lock-path=/var/run/nginx.lock \
  --error-log-path=/var/log/nginx/error.log \
  --http-log-path=/var/log/nginx/access.log \
  --with-threads \
  --with-file-aio \
  --with-http_ssl_module \
  --with-http_v2_module \
  --with-http_v3_module \
  --with-http_realip_module \
  --with-http_sub_module \
  --with-http_gzip_static_module \
  --with-http_auth_request_module \
  --with-http_secure_link_module \
  --with-http_stub_status_module \
  --with-stream \
  --with-stream_ssl_module \
  --with-stream_realip_module \
  --with-stream_ssl_preread_module \
  --with-compat \
  --add-dynamic-module=../ngx_http_geoip2_module \
  --with-openssl=../openssl-4.0.1 \
  --with-openssl-opt="no-tests" \
  --with-cc-opt='-march=native -O3'
#编译/安装 nginx
make -j$(nproc) && make install
#安装wordpress
cd .. && wget -P /usr/local/nginx/html/ https://cn.wordpress.org/latest-zh_CN.zip && unzip /usr/local/nginx/html/latest-zh_CN.zip -d /usr/local/nginx/html/ && mv /usr/local/nginx/html/wordpress/* /usr/local/nginx/html && rm -rf /usr/local/nginx/html/latest-zh_CN.zip /usr/local/nginx/html/wordpress
#删除已使用文件
rm -rf libmaxminddb-1.13.3 nginx-1.30.3 nginx-1.30.3.tar.gz ngx_http_geoip2_module openssl-4.0.1
# 创建目录和设置权限.
mkdir -p /etc/nginx/ssl /etc/nginx/GeoLite2 /var/log/nginx /etc/init.d /run/php-fpm83
touch /var/log/nginx/access.log /var/log/nginx/error.log
chown -R nobody:nobody /usr/local/nginx/html /var/log/nginx
sed -i 's|#pid.*logs/nginx.pid;|pid /var/run/nginx.pid;|g' /etc/nginx/nginx.conf
sed -i 's|#user  nobody;|user  nobody;|g' /etc/nginx/nginx.conf
sed -i '/user  nobody;/a \
load_module /usr/local/nginx/modules/ngx_http_geoip2_module.so;\
load_module /usr/local/nginx/modules/ngx_stream_geoip2_module.so;' /etc/nginx/nginx.conf
sed -i 's|worker_processes\s*1;|worker_processes  auto;|g' /etc/nginx/nginx.conf

下载GeoLite2-Country数据

wget -O /etc/nginx/GeoLite2/GeoLite2-Country.mmdb \
  https://raw.githubusercontent.com/P3TERX/GeoLite.mmdb/download/GeoLite2-Country.mmdb

GeoIP2 国家识别

sed -i '/http {/a \
    # GeoIP2 Country Identification\n    map $http_x_forwarded_for $clientRealIp {\n        "" $remote_addr;\n        ~^(?P<firstAddr>[0-9\\.]+),?.*$ $firstAddr;\n    }\n\n    geoip2 /etc/nginx/GeoLite2/GeoLite2-Country.mmdb {\n        auto_reload 5m;\n        $geoip2_data_country_code default=XX source=$clientRealIp country iso_code;\n    }\n\n    map $geoip2_data_country_code $allowed_country {\n        CN      yes;\n        JP      yes;\n        HK      yes;\n        US      yes;\n        CA      yes;\n        FR      yes;\n        default no;\n    }' /etc/nginx/nginx.conf
#安装nginx配置文件
vim /etc/nginx/nginx.conf
  • server {下的
  • location / {添加
	if ($allowed_country = no) {
	    return 404;
	}

添加dhparam

curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/nginx/ssl/dhparam

修改 PHP-FPM 配置文件

sed -i 's|127.0.0.1:9000|/run/php-fpm83/www.sock|' /etc/php83/php-fpm.d/www.conf
sed -i 's|;listen.owner = nobody|listen.owner = nobody|' /etc/php83/php-fpm.d/www.conf
sed -i 's|;listen.group = nobody|listen.group = nobody|' /etc/php83/php-fpm.d/www.conf
sed -i 's|;listen.mode = 0660|listen.mode = 0660|' /etc/php83/php-fpm.d/www.conf

初始化数据库 MariaDB

mariadb-install-db --user=mysql --datadir=/var/lib/mysql

添加自启动脚本

cat > /entrypoint.sh <<EOF
#!/bin/sh

# 1. 初始化 MariaDB 数据库目录
if [ ! -d "/var/lib/mysql/mysql" ]; then
    echo "初始化 MariaDB 数据库..."
    mariadb-install-db --user=mysql --datadir=/var/lib/mysql > /dev/null
fi

# 2. 启动 MariaDB(后台运行)
echo "正在启动 MariaDB..."
/usr/bin/mariadbd-safe --user=mysql --datadir=/var/lib/mysql &

# ★★★ 核心优化:等待 MariaDB 真正启动完毕 ★★★
echo "等待 MariaDB 完全启动..."
while ! mysqladmin ping --silent; do
    sleep 1
done
echo "MariaDB 已就绪!"

# 3. 修复 PHP-FPM 报错:自动创建缺失的 runtime 目录
echo "检查并创建 PHP-FPM 运行目录..."
mkdir -p /run/php-fpm83

# 4. 启动 PHP-FPM (后台运行)
echo "正在启动 PHP-FPM..."
/usr/sbin/php-fpm83 -D

# 5. 启动 Nginx (前台运行)
echo "正在启动 Nginx..."
exec /usr/local/nginx/sbin/nginx -g "daemon off;"
EOF

# 给脚本赋予可执行权限
chmod +x /entrypoint.sh

退出 容器

#键盘:
Ctrl+P+Q
  • 在宿主机上锁定这个位置(最关键)脚本写在 /entrypoint.sh 后,必须在宿主机上通过 docker commit 告诉 Docker:“以后容器开机,就去执行根目录下的这个脚本”。
  • 在宿主机执行:docker001/alpine3.24:v1
docker commit --change='ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]' 'CONTAINER ID' 'docker注册用户名/daocker建的库名:标签
#======推送(Push)镜像到云端=========
# 给本地镜像打标签(Tag)
# Docker 规定,上传镜像前必须把镜像名字改成 用户名/仓库名:标签 的格式,否则 Docker 不知道你想往谁的家门口送。在宿主机执行:
docker commit --change='ENTRYPOINT ["/bin/sh", "/entrypoint.sh"]' 'CONTAINER ID' 'docker001/alpine3.24:v1'
#推送(Push)镜像到云端
docker login -u <用户名>
docker push docker001/alpine3.24:v1
#======同步下载(Pull)镜像到本地=========
#在宿主机终端执行登录命令,输入你的账号密码(或者 Access Token):
docker login -u <用户名>
docker pull docker001/alpine3.24:v1
#=====================================
删掉旧容器
docker stop alpine
docker rm -f alpine
docker run -itd \
  -p 80:80 \
  -p 443:443/tcp \
  -p 443:443/udp \
  -e TZ=Asia/Shanghai \
  --restart=always \
  -v /var/log/nginx:/var/log/nginx \
  --name alpine \
  docker001/alpine3.24:v1
#进入容器
docker exec -it alpine /bin/sh

mysql或MariaDB安全加固:会设置密码,界面1直接回车,界面2选N,剩的都选Y

mysql_secure_installation

root登录:

mysql -u root -p
#创建数据库:
CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

#创建用户
CREATE USER 'wp_user'@'localhost' IDENTIFIED BY '你的安全密码';

#授予权限:
GRANT ALL PRIVILEGES ON wordpress.* TO 'wp_user'@'localhost';

#最后务必刷新权限
FLUSH PRIVILEGES;
#退出:
exit
vi /etc/nginx/nginx.conf
#===========80端口测试=========
        location / {                                                        
            root   html;                                                    
            index  index.html index.htm;                                    
        }
#---------------修改为-----------------------------------------------
        location ~ \.php$ {
            fastcgi_pass unix:/run/php-fpm83/www.sock;
            fastcgi_index index.php;
            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
            root  /usr/local/nginx/html;
            index index.php index.html index.htm;
#重新加载配置文件,不重启服务
/usr/local/nginx/sbin/nginx -s reload

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注