Docker Compose一键部署LNMP环境全攻略

一、架构设计与服务规划

二、项目结构准备

lnmp-docker/
├── docker-compose.yml
├── nginx/
│   ├── conf.d/
│   │   └── app.conf
│   └── nginx.conf
├── php/
│   └── Dockerfile
├── mysql/
│   └── my.cnf
├── html/
│   └── index.php
└── .env

三、核心配置文件

3.1 docker-compose.yml

ersion: '3.8'

services:
  # Web服务
  nginx:
    image: nginx:1.25-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./html:/var/www/html
      - ./ssl:/etc/nginx/ssl
    depends_on:
      php:
        condition: service_healthy
    networks:
      - lnmp-net

  # PHP处理
  php:
    build: ./php
    volumes:
      - ./html:/var/www/html
    environment:
      - TZ=Asia/Shanghai
    healthcheck:
      test: ["CMD", "php-fpm", "-t"]
      interval: 10s
      timeout: 5s
      retries: 3
    networks:
      - lnmp-net

  # 数据库
  mysql:
    image: mysql:8.0-debian
    volumes:
      - mysql_data:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    networks:
      - lnmp-net

  # 数据库管理
  phpmyadmin:
    image: phpmyadmin:5.2
    ports:
      - "8080:80"
    environment:
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=${DB_ROOT_PASSWORD}
    depends_on:
      - mysql
    networks:
      - lnmp-net

volumes:
  mysql_data:

networks:
  lnmp-net:
    driver: bridge

3.2 PHP Dockerfile

FROM php:8.2-fpm-alpine

# 安装扩展
RUN apk add --no-cache \
    freetype-dev \
    libjpeg-turbo-dev \
    libpng-dev \
    libzip-dev \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd pdo_mysql mysqli zip opcache

# 生产环境优化
RUN { \
    echo 'opcache.enable=1'; \
    echo 'opcache.memory_consumption=128'; \
    echo 'opcache.max_accelerated_files=10000'; \
    echo 'opcache.revalidate_freq=60'; \
} > /usr/local/etc/php/conf.d/opcache.ini

WORKDIR /var/www/html

3.3 Nginx配置

# nginx/conf.d/app.conf
server {
    listen 80;
    server_name localhost;
    
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }
}

四、环境变量配置(.env)

# 数据库配置
DB_ROOT_PASSWORD=SuperSecretRootPass!
DB_NAME=app_prod
DB_USER=app_user
DB_PASSWORD=UserStrongPass123

# 时区配置
TZ=Asia/Shanghai

五、部署与验证

5.1 启动命令

# 构建并启动服务
docker compose up -d --build

# 查看服务状态
docker compose ps

# 查看实时日志
docker compose logs -f

5.2 环境验证

<?php
// html/index.php
phpinfo();

// 测试数据库连接
try {
    $pdo = new PDO(
        'mysql:host=mysql;dbname='.getenv('DB_NAME'),
        getenv('DB_USER'),
        getenv('DB_PASSWORD')
    );
    echo "Database connection OK!";
} catch (Exception $e) {
    echo "Connection failed: " . $e->getMessage();
}

六、生产环境优化建议

1.SSL加密:在nginx配置中添加443端口SSL证书

2.资源限制:在compose文件中添加资源限制

deploy:
  resources:
    limits:
      cpus: '2'
      memory: 1G

3.日志切割:配置logrotate管理容器日志

4.备份策略:定时备份MySQL数据卷

docker compose exec mysql sh -c 'exec mysqldump --all-databases -uroot -p"$MYSQL_ROOT_PASSWORD"' > backup.sql

摘自:https://blog.csdn.net/u011570324/article/details/147523961

vim一键运行Python/C/C++/go

vim一键运行Python、C、C++、go、html

" 用<F5>运行
noremap <silent> <F5> :call CompileRun()<CR>
func! CompileRun()
    exec "w"
    let g:asyncrun_open = 10
    let g:asyncrun_bell = 1
    let l:filename = expand('%:t')          " 文件名,如 main.c
    let l:filepath = expand('%:p')          " 完整路径
    let l:filedir = expand('%:p:h')         " 文件目录
    let l:filenamenoext = expand('%:t:r')   " 无后缀文件名,如 main
    let l:exe = l:filedir . '/' . l:filenamenoext  " 可执行文件路径
    if &filetype == 'c'
        exec ":AsyncRun -mode=term -pos=bottom -rows=10 -focus=0 gcc -Wall -O2 \"" . l:filepath . "\" -o \"" . l:exe . "\" && \"" . l:exe . "\""
    elseif &filetype == 'cpp'
        exec ":AsyncRun -mode=term -pos=bottom -rows=10 -focus=0 g++ -Wall -O2 -std=c++13 \"" . l:filepath . "\" -o \"" . l:exe . "\" && \"" . l:exe . "\""
    elseif &filetype == 'python'
        exec ":AsyncRun -mode=term -pos=bottom -rows=10 -focus=0 python3 \"" . l:filepath . "\""
    ""elseif &filetype == 'html'
        " Linux 下使用 xdg-open,静默打开浏览器
        ""exec ":AsyncRun -mode=term -pos=hide firefox \"" . l:filepath . "\""
    elseif &filetype == 'html'
    if executable('xdg-open')
        exec ":AsyncRun -mode=term -pos=hide nohup xdg-open \"" . l:filepath . "\" > /dev/null 2>&1 &"
    else
        echo "xdg-open not found! Run: sudo apt install xdg-utils"
    endif
    elseif &filetype == 'go'
        exec ":AsyncRun -mode=term -pos=bottom -rows=10 -focus=0 go run \"" . l:filepath . "\""
    elseif &filetype == 'javascript'
        exec ":AsyncRun -mode=term -pos=bottom -rows=10 -focus=0 node \"" . l:filepath . "\""
    else
        echo "Unsupported filetype: " . &filetype
    endif
endfunc

提前安装 AsyncRun.vim 插件

可选:清理旧可执行文件(防止缓存) 在函数开头加:

silent! exec “!rm -f \”” . l:exe . “\””

屏蔽百度搜索百家号文章

百家号都是一些垃圾文章,搜索结果每页都能占用一半,屏蔽了眼不见心不烦。

现在也不用百度,用Google或者Bing

// ==UserScript==
// @name 屏蔽百度搜索百家号文章
// @namespace https://github.com/tengxunlaozu/baijiahao
// @version 1.0
// @description 屏蔽百度搜索结果中的百家号文章
// @author tengxunlaozu
// @match ://.baidu.com/*
// ==/UserScript==

(function() {
‘use strict’;

// 创建样式隐藏百家号元素
const style = document.createElement('style');
style.textContent = `
    div[data-tuiguang*='baijiahao'],
    div[id*='baijiahao'],
    div[class*='baijiahao'],
    a[href*='baijiahao.baidu.com'] {
        display: none !important;
    }
`;
document.head.appendChild(style);

// MutationObserver 监控页面动态加载内容
const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
        if (mutation.addedNodes.length) {
            // 查找并隐藏百家号相关元素
            document.querySelectorAll('div[data-tuiguang*="baijiahao"], div[id*="baijiahao"], div[class*="baijiahao"], a[href*="baijiahao.baidu.com"]').forEach(element => {
                element.style.display = 'none';
            });
        }
    });
});

// 观察页面变化
observer.observe(document.body, {
    childList: true,
    subtree: true
});

// 初始隐藏页面中的百家号内容
document.querySelectorAll('div[data-tuiguang*="baijiahao"], div[id*="baijiahao"], div[class*="baijiahao"], a[href*="baijiahao.baidu.com"]').forEach(element => {
    element.style.display = 'none';
});

})();

或者直接链接:https://github.com/tengxunlaozu/baijiahao

Sublime Text4配置c#补全并运行

c#开发的小项目准备扔给我,提前把基础语法过一遍

1,安装sdk:https://dotnet.microsoft.com/zh-cn/download

2,在sublime安装Omnisharp

3,安装msbuild(否则omnisharp报错:Error talking to http://localhost:60375/checkreadystatus)

4,在sublime安装LSP-Omnisharp(前提已安装LSP)

5,新建编译系统c#:

{
“cmd”: [“dotnet”, “run”, “–project”, “$file_path”],
“working_dir”: “$file_path”,
“selector”: “source.cs”,
“shell”: true,
“encoding”: “utf-8”,
“variants”: [
{
“name”: “Run”,
“cmd”: [“dotnet”, “run”, “–project”, “$file_path”]
}
]
}

6,在lsp-setting配置:

// Settings in here override those in “LSP/LSP.sublime-settings”
{
“clients”: {
“pylsp”: {
“enabled”: true,
“command”: [“pylsp”],
“selector”: “source.python”,
“settings”: {
“pylsp.plugins.jedi_completion.enabled”: true,
“pylsp.plugins.jedi_completion.include_params”: true,
“pylsp.plugins.pylsp_mypy.enabled”: true,
“pylsp.plugins.flake8.enabled”: true,
“pylsp.plugins.pylsp_black.enabled”: false,
“pylsp.plugins.pylsp_isort.enabled”: false
}
},
“omnisharp”: {
“enabled”: true,
“command”: [“dotnet”, “C:/Users/Administrator/AppData/Local/Sublime Text/Package Storage/LSP-OmniSharp/OmniSharp.dll”],
“args”: [“–hostPID”, “${pid}”, “–hostIpc”, “pipes”, “–threads”, “1”],
“selector”: “source.cs”,
“settings”: {
“DotNetPath”: {
“Path”: “C:\Program Files\dotnet\dotnet.exe”
},
“RoslynExtensionsOptions”: {
“EnableEditorConfigSupport”: true,
“LocationPaths”: []
},
“FormattingOptions”: {
“EnableEditorConfigForFormatting”: true
},
“OmniSharp”: {
“UseGlobalMono”: “never”,
“RoslynServerPort”: “60777”,
“SdkVersion”: “8.0.414” // 替换为您的 dotnet –version 输出
}
}
}
}
}

用Python语言把excel内base64文本内容转成图片直接在excel中显示

import base64
import io
import openpyxl
from openpyxl.drawing.image import Image
from openpyxl.utils import units

def process_excel_file(input_file, output_file, base64_col, image_col):
    # 加载输入工作簿
    wb = openpyxl.load_workbook(input_file)
    ws = wb.active  # 假设处理的是活动工作表

    # 单元格尺寸转换因子
    # Excel 列宽单位转换为像素(近似,取决于 DPI 和字体设置)
    # 1 单位宽度 ≈ 7 像素(基于默认字体)
    # 行高以点为单位,1 点 ≈ 1.333 像素(假设 96 DPI)
    pixels_per_width_unit = 7
    pixels_per_point = 1.333

    # 遍历第 2 到第 6 行(对应 V2 到 V6 单元格)
    for row in range(2, 7):
        # 获取指定列(例如 'V')中的 base64 字符串
        base64_cell = ws[f"{base64_col}{row}"]
        base64_string = base64_cell.value

        # 检查单元格是否包含有效的 base64 字符串
        if base64_string and isinstance(base64_string, str) and base64_string.startswith("data:image/png;base64,"):
            try:
                # 提取 base64 数据(去除前缀)
                base64_data = base64_string.split(",")[1]
                # 将 base64 字符串解码为字节
                img_data = base64.b64decode(base64_data)
                # 创建 BytesIO 对象以存储图像数据
                img_io = io.BytesIO(img_data)
                # 为 openpyxl 创建 Image 对象
                img = Image(img_io)

                # 获取目标单元格(例如 AC2)的尺寸
                target_cell = f"{image_col}{row}"
                col_idx = openpyxl.utils.column_index_from_string(image_col) - 1
                # 获取列宽(Excel 单位,默认 8.43 如果未设置)
                col_width = ws.column_dimensions[image_col].width or 8.43
                # 获取行高(点,默认 12.75 如果未设置)
                row_height = ws.row_dimensions[row].height or 12.75

                # 将单元格尺寸转换为像素
                img_width_pixels = col_width * pixels_per_width_unit
                img_height_pixels = row_height * pixels_per_point

                # 设置图片尺寸以匹配单元格大小
                img.width = img_width_pixels
                img.height = img_height_pixels

                # 将图片锚定到目标单元格(例如 AC2)
                img.anchor = target_cell

                # 将图片添加到工作表
                ws.add_image(img, target_cell)
            except Exception as e:
                print(f"处理第 {row} 行图像时出错:{e}")
        else:
            print(f"{base64_col}{row} 中没有有效的 base64 图像数据")

    # 保存输出工作簿
    wb.save(output_file)
    print(f"Excel 文件成功保存到 {output_file}")

# 示例用法
input_excel = "input.xlsx"
output_excel = "output.xlsx"
base64_col = "V" # V是base64所在列
image_col = "AC" # AC为生成图片所在列
process_excel_file(input_excel, output_excel, base64_col, image_col)