返回
Featured image of post 网站容器化部署实践

网站容器化部署实践

今天尝试了使用docker来分别部署php、nginx、mysql三个容器,并让他们协同工作,将我的图床迁移到了docker中。

网站容器化部署实践

最近将原来的网站从wordpress迁移到了hugo并将原来的两个域名下的网站合并成了一个,并迁移到了另一台服务器上,于是之前使用的服务器只剩下一个图床服务了,之前在使用的时候没怎么注意文件规范,导致服务器就像一个从来没有打扫过卫生的房间——配置文件、应用程序等各种文件乱糟糟的,看上去就很不舒服。

今天在升级系统的时候不知道为什么整个mysql都消失了,幸好服务器有远程备份服务,在将备份还原之后想着与其收拾半天干脆推倒重来,并尝试一下使用docker来部署图床。

准备工作

为了后面能够更直观的操作容器,我先使用 docker network create web 创建了一个docker网络。另外考虑到是要迁移网站,所以使用 mysqldump -u chevereto -p chevereto > chevereto.sql 导出了数据库。

另外,我的服务器有一块系统盘和一块数据盘,这里我修改docker的储存路径到数据盘上。 nano /etc/docker/daemon.json ,添加如下内容:

{
  "data-root": "/mnt/storage/docker"
}

之后使用 systemctl restart docker 重启docker即可。

数据库

我们首先将数据库改为容器部署,为了避免后续可能出现的问题,这里我都指明了镜像的版本号,当然你也可以省略版本号,改为使用最新镜像。

# 创建一个专门储存数据的文件夹
mkdir -p /mnt/storage/docker/data/mysql-data
# 创建建一个用于储存配置文件的文件夹
mkdir -p /mnt/storage/docker/config/mysql/conf.d

docker run \
--detach \
--name=mysql \
--network=web \ # 加入了我们之前创建的docker网络 “web”
--env="MYSQL_ROOT_PASSWORD=[my_password]" \
--publish 127.0.0.1:3306:3306 \
--volume=/mnt/storage/docker/mysql/config/mysql/conf.d:/etc/mysql/conf.d \
--volume=/mnt/storage/docker/data/mysql-data:/var/lib/mysql \
mysql:8.0

之后只需要在宿主机上apt install default-mysql-client安装客户端即可操控容器中的数据库,当然也可以 docker exec -it mysql bash 进入容器操作。

注意,mysql-client默认会使用socket连接数据库,但是我前面没有将socket暴露出来,所以要指明使用tcp连接 mysql -h localhost -P 3306 --protocol=tcp -u root -p,另一个解决方法是将socket所在目录使用挂载的方式暴露出来 -v /var/run/mysqld:/var/run/mysqld,接着创建用户以及数据库并导入原有的数据库。

CREATE USER 'chevereto'@'%' IDENTIFIED BY '123456';
CREATE DATABASE chevereto;
GRANT ALL ON chevereto.* TO chevereto;

之后使用 mysql -h localhost -P 3306 --protocol=tcp -u root -p chevereto < ./chevereto.sql 导入数据。

php

配置好数据库之后我们来安装php,考虑到网站使用php可能需要一些扩展,但是php的docker镜像里面可能还没装上这些扩展,有两种解决方式:

  1. 进入docker镜像后使用apt安装扩展
  2. 以已有的镜像为基础,自己构建一个镜像

然后docker build -t myphp . 构建镜像。

尤其注意 php的容器也要能读到站点文件夹目录,这里需要和下面nginx启动时挂载的路径一致

因为安装扩展有些麻烦,所以我没用官方的镜像

docker run -d --name php --network web \
-v /var/www/html:/usr/share/nginx/html/mount \
phpdockerio/php74-fpm

另外 docker中的容器可能没权限修改挂载的数据卷中的文件,需要使用 chmod -R 777 chevereto/ 命令来赋予权限(应该是有更好的方法的,但是我暂时没看, 可以参考 https://padeoe.com/docker-volume-file-permission-problem/

如果还是存在权限问题,可能还需要进入到容器中再次执行chmod。

nginx

mkdir -p /mnt/storage/config/nginx/conf.d
mkdir -p /var/log/nginx
mkdir /mnt/storage/config/nginx/ssl
mkdir -p /var/www/html

需要在 /mnt/storage/config/nginx/conf.d 里面创建默认配置文件 default.conf 如下

server {
    listen       80 default_server;
    listen  [::]:80 default_server;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}

然后启动容器

docker run -d --network web --name nginx -p 80:80 -p 443:443 \
    -v /var/www/html:/usr/share/nginx/html/mount \
    -v /mnt/storage/config/nginx/conf.d:/etc/nginx/conf.d \
    -v /mnt/storage/config/nginx/ssl:/etc/nginx/ssl \
    -v /var/log/nginx:/var/log/nginx \
    nginx

修改网站配置

之后修改网站配置,将这几个容器关联起来即可,我的配置文件如下: (之后可能还要按照需求修改一下网站配置中的数据库配置)

注意 fastcgi_param 后面的路径一定要填站点文件夹的路径或者$document_root$fastcgi_script_name ,不然会出现 Primary script unknown 错误。

server {
    listen       80;
    listen  [::]:80;
    server_name  img.aoyouer.com;

    if ($host = img.aoyouer.com) {
        return 301 https://$host$request_uri;
    }
}

server {
    root /usr/share/nginx/html/mount/chevereto;
    index index.html index.htm index.nginx-debian.html index.php;
    server_name img.aoyouer.com;

    access_log  /var/log/nginx/img.access.log  main;
    error_log   /var/log/nginx/img.error.log error;

    location / {
           try_files $uri $uri/ =404;
    }
    
    location ~ \.php$ {
        fastcgi_pass   php:9000;
        fastcgi_index  index.php;
        # 万分注意 下面的路径一定要改成站点文件夹的路径
        fastcgi_param  SCRIPT_FILENAME /usr/share/nginx/html/mount/$fastcgi_script_name;
        include        fastcgi_params;
    }

    listen [::]:443 ssl http2;
    listen 443 ssl http2;
    ssl_certificate /etc/nginx/ssl/aoyouer.com.cer;
    ssl_certificate_key /etc/nginx/ssl/aoyouer.com.key;
}

反向代理示例(比如我想反向代理umami的端口)

location / {
    proxy_pass http://umami:3000;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

修改好配置后,让nginx重新加载配置文件:docker exec -it nginx nginx -s reload

之后只需要将站点文件夹移动到 /var/www/html 中即可。

后记

将网站容器化之后想要更新版本或者是进行迁移都方便了很多,不用再担心不同的个系统中软件版本不一致导致一些莫名其妙的BUG,迁移的时候只需要把几个配置文件夹和数据文件夹一起迁移过去即可。

参考

Docker Network命令

https://phoenixnap.com/kb/mysql-docker-container

https://padeoe.com/docker-volume-file-permission-problem/

comments powered by Disqus
本站访客数:
Built with Hugo
Theme Stack designed by Jimmy