fanyi 这个小工具,以前是直接跑在腾讯云的轻量服务器上的,用 Golang 写的,最近加了一个小功能,用 php 重写了,php 就要搭建各种环境,直接在腾讯云的轻量服务器上编译 php 不成功,主要是你 cpu 高,他就直接给你 kill 了,所以就用 docker 来解决。
构建 PHP 的运行环境
从 php:8.1-fpm 开始构建,安装上相关依赖,然后设置运行用户的相关权限。
vim Dockerfile
FROM php:8.1-fpm
# Arguments defined in docker-compose.yml
ARG user
ARG uid
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
curl \
libpng-dev \
libonig-dev \
libxml2-dev \
zip \
unzip
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install PHP extensions
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Get latest Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# Create system user to run Composer and Artisan Commands
RUN useradd -G www-data,root -u $uid -d /home/$user $user
RUN mkdir -p /home/$user/.composer && \
chown -R $user:$user /home/$user
# Set working directory
WORKDIR /var/www
USER $user
编排文件
把 PHP,nginx,mysql 8.0 编排在一起。
vim docker-compose.yml
version: "3.7"
services:
app:
build:
args:
user: lighthouse
uid: 1000
context: ./
dockerfile: Dockerfile
image: travellist
container_name: travellist-app
restart: unless-stopped
working_dir: /var/www/
volumes:
- ./:/var/www
networks:
- travellist
db:
image: mysql:8.0
container_name: travellist-db
restart: unless-stopped
environment:
MYSQL_DATABASE: ${DB_DATABASE}
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
MYSQL_PASSWORD: ${DB_PASSWORD}
MYSQL_USER: ${DB_USERNAME}
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- ./mysql/:/var/lib/mysql
networks:
- travellist
nginx:
image: nginx:alpine
container_name: travellist-nginx
restart: unless-stopped
ports:
- 8000:80
volumes:
- ./:/var/www
- ./docker-compose/nginx:/etc/nginx/conf.d/
networks:
- travellist
networks:
travellist:
driver: bridge
坑
权限的问题,如果 php 没有写的权限,一定是 user: lighthouse, uid: 1000
设置的不对,这个 user 必须在系统中存在,且 uid 一定要对。
Nginx 配置
容器里面的 nginx 需要把请求转发给 php-fpm
vim vim docker-compose/nginx/travellist.conf
server {
listen 80;
index index.php index.html;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/public;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location / {
try_files $uri $uri/ /index.php?$query_string;
gzip_static on;
}
}
负载 nginx 配置
为什么要加这个 nginx,其实也可以不加,主要是这个机器上我还跑了另外几个服务,所以才共用这个 负载 nginx。
server {
server_name fanyi1.qishiya.com;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Forward-For $remote_addr;
proxy_set_header Host fanyi1.qishiya.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Appengine-Remote-Addr $remote_addr;
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/fanyi.qishiya.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/fanyi.qishiya.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
坑
在负载的 nginx,不加 host 的话,取不到 host,默认的资源依赖都变成 127.0.0.1
proxy_set_header Host fanyi1.qishiya.com;
Laravel 配置
一定要配置 APP_URL 和 ASSET_URL,不然取的资源的域名不对。
APP_URL=https://fanyi1.qishiya.com
ASSET_URL=https://fanyi1.qishiya.com
强制 https,laravel 在前端模板调用 {{ router(‘login’) }} 之类的指令时,默认是 http,修改如下代码,可以强制 https
namespace App\Providers;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
URL::forceScheme('https');
}
}
laravel 初始化
服务跑起来后,需要对环境进行初始化。
docker compose exec app composer install
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate --force
参考
https://stackoverflow.com/questions/28402726/laravel-5-redirect-to-https