顯示具有 apache 標籤的文章。 顯示所有文章
顯示具有 apache 標籤的文章。 顯示所有文章

2022/10/18

Reload Nginx And Apache Config In Docker

如果在本機安裝 apache2 或 nginx 時想要 reload config 的話我們通常會使用下列的指令:

# nginx
nginx -s reload

# apache2
service httpd reload

但在 docker 的環境下就沒有那麼簡單,像 apache 的 reload 是把 script 寫在 service 的 config 裡面,不一定每個 image 裡面都有包含這個指令,CentOS 的我記得好像就沒有,為了要兼容所有的環境,我們可以利用 kill -USR1 這個方式套用到每個我們想要 reload without restart 的專案上面。

apache2

首先在根目錄建立兩個網頁檔:

  • ./www/1/index.html
  • ./www/2/index.html

各別會在網頁印出 1 以及 2 的內容識別。

docker-compose.yml

version: "3.9"

services:
  http:
    ports:
      - "80:80"
    container_name: httpd
    image: httpd
    restart: always
    volumes:
      - "./www:/www"
      - "./config/httpd:/usr/local/apache2/conf:ro"

我們建立了一個名為 http 的 container,使用 httpd 的 image,並且把 www 目錄掛進去,我事先把 httpd 的 config 複製出來以便在外面修改內容,接下來跑 docker compose up -d,打上 IP 後可以看到 httpd 傳統的首頁內容 It works!

接著我們修改 httpd.conf

DocumentRoot "/usr/local/apache2/htdocs"
<Directory "/usr/local/apache2/htdocs">

# 改為

DocumentRoot "/www/1"
<Directory "/www/1">

我們先使用 docker compose restart 測試,執行後 refresh 網頁可以看到我們要的 1,接著再把 config 改成:

DocumentRoot "/www/2"
<Directory "/www/2">

這次我們使用 docker compose kill -s USR1 http ,此時我們可以看到 container 活得好好的,但 refresh 頁面後得到我們想要的 2 了,他的原理就是呼叫 container 內的 httpd daemon 去重新整理他的 service。

nginx

docker-compose.yml

version: "3.9"

services:
  http:
    ports:
      - "80:80"
    container_name: nginx
    image: nginx
    restart: always
    volumes:
      - "./www:/www"
      - "./config/nginx/conf.d/default.conf:/etc/nginx/conf.d/default.conf:ro"

一樣,我們事前複製了 nginx 的 config 出來重新掛載回去,啟動 container 以後看見 nginx 的預設字樣 Welcome to nginx!

接著我們修改 defalut.conf

root   /usr/share/nginx/html;

# 改為

root   /www/1;

跟 apache2 一樣我們先使用 docker compose restart,可以順利看到 1 的結果,接著我們將 config 修改為:

root   /www/2;

使用 docker compose exec http nginx -s reload,我們就可以順利看到 2 了,nginx 跟 apache2 的 container 啟動方式不太一樣,所以不能用 kill 的方法,但事實上在 nginx 的 logrotate config 裡面他使用的方式也是:

kill -USR1 `cat /var/run/nginx.pid`

上面介紹了兩個主流網頁伺服器的重取 config 的目的是在當我們把 server 的 log 掛到我們本機目錄時,我們可能會需要依照情況在本機執行 logrotate 的動作,這樣就可以把 reload 腳本寫在本機的 logrotate config 的 postrotate/endscript 裡面了。

這邊附上 logrotate for docker 基本的配置:

nginx-docker

/YOUR_PATH_TO_LOG/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 nginx adm
        sharedscripts
        postrotate
            sudo docker exec YOUR_CONTAINER_NAME nginx -s reload
        endscript
}

httpd-docker

/YOUR_PATH_TO_LOG/*.log {
        daily
        missingok
        rotate 14
        compress
        delaycompress
        notifempty
        sharedscripts
        postrotate
            sudo docker kill -s USR1 YOUR_CONTAINER_NAME 
        endscript
}

2022/07/06

Compile Apache and OpenSSL

OS: CentOS 8
Target:

  • PHP 7.4
  • PHP-FPM
  • Apache 2.4.46
  • OpenSSL 1.1.1g

Start compile

sudo dnf install install -y gcc gcc-c++ make prec-devel libtool perl-core zlib-devel

# Compile apr
sudo ./configure --prefix=/usr/local/apr
sudo make
sudo make install

# Compile apr-util
sudo ./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr
sudo make
sudo make install

# Compile openssl
sudo ./config --prefix=/usr/local/openssl --openssldir=/usr/local/openssl shared zlib
sudo make
sudo make install

# Compile apache
sudo ./configure --prefix=/usr/local/apache2446 --enable-so --enable-ssl --enable-cgi --enable-rewrite --enable-modules=most --enable-mpms-shared=all --with-mpm=prefork --with-zlib --with-apr=/usr/local/apr --with-apr-util=/usr/local/apr-util --with-ssl=/usr/local/openssl
sudo make
sudo make install

# Apache system configuration
# Add Apache executables to PATH ( You can use nano instead of vi)
# create and open the following file
sudo vim /etc/profile.d/httpd.sh
  
# paste the following content, save and exit
pathmunge /usr/local/apache2446/bin

# Add Systemd entry

# create and open the following file
sudo vim /etc/systemd/system/httpd.service

paste the following content, save and exit.

[Unit]
Description=The Apache HTTP Server
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/apache2446/bin/apachectl -k start
ExecReload=/usr/local/apache2446/bin/apachectl -k graceful
ExecStop=/usr/local/apache2446/bin/apachectl -k graceful-stop
PIDFile=/usr/local/apache2446/logs/httpd.pid
PrivateTmp=true

[Install]
WantedBy=multi-user.target
# reload the systemctl daemon
sudo systemctl daemon-reload

# start Apache httpd server (ignore the warnings at this stage)
sudo systemctl start httpd
sudo systemctl enable httpd

# Install PHP
sudo dnf install -y http://rpms.remirepo.net/enterprise/remi-release-8.rpm
dnf module reset php
dnf module install -y php:remi-7.4

sudo service php-fpm start
sudo systemctl enable php-fpm

Reference

2020/12/01

php-fpm config

apache 跟 nginx 都有接觸,nginx 上本就是用 php-fpm 跟 php 溝通,現在 apache 上我也捨棄內建的 php module,改用 fcgi 去溝通了,有幾個好處:

  1. apache 內建 php module 必須綁死 php 版本
  2. 因為綁死 php 版本如果有使用 virtual host 的話要做到每個網站跑自己的 php 版本很麻煩
  3. php-fpm 效能以及穩定性綜合值應該是優於 apache php module

在 Ubuntu 上我選擇了 ondrej/php 當作 repo

sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
apt install php7.3 php7.3-fpm

CentOS 上使用 remi

dnf install dnf-utils http://rpms.remirepo.net/enterprise/remi-release-8.rpm
dnf module reset php
dnf module enable php:remi-7.4
dnf install php

Config

Apache

Through socket file
<VirtualHost>
    # someting config
    <FilesMatch \.php$>
        SetHandler "proxy:unix:/var/run/php/php7.2-fpm.sock|fcgi://localhost/"
    </FilesMatch>    
</VirtualHost>
Through port
<VirtualHost>
    # someting config
    <FilesMatch \.php$>
        setHandler "proxy:fcgi://127.0.0.1:9000"
    </FilesMatch>  
</VirtualHost>

Apache 使用上必須確定 proxy_module 以及 proxy_fcgi_module 這兩個 module 有開啟,前者必須在後者上方先載入。

Nginx

location ~* \.php$ {
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_split_path_info ^(.+\.php)(.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}

Reference

2020/11/26

Temporary SSL config for Apache and Nginx

開發時需要測試 ssl 的功能或配置結果但不需要真的 ssl 證書時,我們可以生成自己的 ssl 配置在本機使用 https 連入。

生成證書

openssl req -nodes -newkey rsa:2048 -sha256 -keyout server.key -out server.csr

# 生成過程其他問題都可以亂填,但 FQDN 必須填對
# 這邊使用 ssl.local 當作測試 domain
# Common Name (e.g. server FQDN or YOUR name) []:ssl.local

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

Nginx config

server {
    listen      443;
    listen  [::]:443;
    server_name  ssl.local;

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

    ssl on;
    ssl_certificate_key /etc/nginx/ssl/server.key;
    ssl_certificate /etc/nginx/ssl/server.crt;

    location ~ /\.ht {
        deny  all;
    }
}

Apache Config

<VirtualHost *:443>
    ServerName ssl.local
    DocumentRoot /var/www/ssl/
 
    SSLEngine on
    SSLCertificateKeyFile /usr/local/apache2/conf/server.key
    SSLCertificateFile /usr/local/apache2/conf/server.crt
    SSLCertificateChainFile /usr/local/apache2/conf/server.crt
 
    <Directory "/var/www/ssl/">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>