docker-compoerでコンテナ名を指定して起動する

container_nameの問題点

dpocker-compose.yml内でcontainer_nameを使ってコンテナ名を指定することができる。

1
2
3
4
5
version: "3"
services:
web:
container_name: app_server
image: php:7.4-apache

しかし、この場合コンテナ名が重複し同じコンテナを複数起動することができない。

1
2
3
4
5
6
7
8
9
10
11
$ sudo docker-compose up -d --scale php=2
WARNING: The "php" service is using the custom container name "app_server". Docker requires each container to have a unique name. Remove the custom name to scale the service.
Creating app_server ... done
Creating app_server ...

ERROR: for app_server Cannot create container for service php: Conflict. The container name "/app_server" is already in use by container
"b4655b49084b30c3fe62bc26b87b997d2f4c6f2bc436594925d7560bxxxxxxxx". You have to remove (or rename) that container to be able to reuse that name.

ERROR: for php Cannot create container for service php: Conflict. The container name "/app_server" is already in use by container
"b4655b49084b30c3fe62bc26b87b997d2f4c6f2bc436594925d7560bxxxxxxxx". You have to remove (or rename) that container to be able to reuse that name.
ERROR: Encountered errors while bringing up the project.

COMPOSE_PROJECT_NAME

.envファイルにCOMPOSE_PROJECT_NAMEを指定すると、指定されたコンテナ名にサービス名<番号>が自動的に設定される。 COMPOSE_PROJECT_NAMEの指定がない場合は、docker-compose.ymlが存在するディレクトリー名になる。

実行例

.envにCOMPOSE_PROJECT_NAMEを設定する。

1
COMPOSE_PROJECT_NAME=app_server

–scaleオプションでコンテナを複数起動する。

1
2
3
4
$ sudo docker-compose up -d --scale php=2
Creating network "app_server_default" with the default driver
Creating app_server_php_1 ... done
Creating app_server_php_2 ... done

コンテナ名に自動的に連番が付与される、複数のコンテナを起動できる。

プロジェクト名を指定してdocker-composeを実行する

同じプロジェクトのコンテナ群を複数起動したい場合には、docker-omposeに-p <プロジェクト名>オプションを付与して実行することで、プロジェクト名を指定してコンテナを起動する。

1
2
3
4
$ sudo docker-compose -p another up -d --scale php=2
Creating network "another_default" with the default driver
Creating another_php_1 ... done
Creating another_php_2 ... done

PHP-FPM-test

Dockerのphp-fpmコンテナを使用しているときに、動作確認をしてみたくなった時のメモ

インストール

Alipine Linuxなら、

1
# apk add fcgi

Debian GNU/Linuxなら、

1
$ sudo apt install libfcgi-bin libfcgi0ldbl

使い方は、こんな感じ

1
2
3
4
5
6
7
8
9
10
11
# cgi-fcgi
Missing application pathname
Missing -connect <connName>
Usage:
cgi-fcgi -f <cmdPath> , or
cgi-fcgi -connect <connName> <appPath> [<nServers>] , or
cgi-fcgi -start -connect <connName> <appPath> [<nServers>] , or
cgi-fcgi -bind -connect <connName> ,
where <connName> is either the pathname of a UNIX domain socket
or (if -bind is given) a hostName:portNumber specification
or (if -start is given) a :portNumber specification (uses local host).

確認用HTML

/var/www/html/index.phpに確認用PHPファイルを設置した。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
$message = 'Hello,world';
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>PHP-FPM test</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

<![endif]-->
<style>
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section { display: block; }
</style>
</head>
<body>
<p><?php echo $message; ?></p>
</body>
</html>

php-fpmのパスを確認する

1
2
3
4
5
6
7
8
9
10
# grep -v "^;" /usr/local/etc/php-fpm.d/www.conf | grep -v "^$"
[www]
user = www-data
group = www-data
listen = 127.0.0.1:9000
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

php-fpmのソケットのパスは127.0.0.1:9000。

確認用スクリプト

1
2
3
4
5
6
#!/bin/ash

SCRIPT_NAME=index.php \
SCRIPT_FILENAME=/var/www/html/index.php \
REQUEST_METHOD=GET \
cgi-fcgi -bind -connect 127.0.0.1:9000

確認

確認用スクリプトを実行すると、PHPが実行されているのが確認できる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# /bin/ash test.sh
X-Powered-By: PHP/7.4.26
Content-type: text/html; charset=UTF-8

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>PHP-FPM test</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

<![endif]-->
<style>
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section { display: block; }
</style>
</head>
<body>
<p>Hello World</p>
</body>
</html>

Nginxでクライアント認証を行う

サーバー認証

まずはじめに、サーバー認証を行いHTTPSで通信できるようにする。

サーバー認証に使用するファイルの保存場所を作成する

1
2
mkdir /etc/nginx/server_certificates
cd /etc/nginx/server_certificates

CA(Certification Authority)鍵を作成する

1
2
3
4
5
6
7
$ openssl genrsa -des3 -out server.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
................................++++
..++++
e is 65537 (0x010001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

CA(Certification Authority)証明書を作成する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ openssl req -new -x509 -days 365 -key server.key -out server.crt
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Shibuya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example, Inc.
Organizational Unit Name (eg, section) []:Infra
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

パスワードファイルを作成する

CA鍵のパスワードをNginxに渡すためパスワードファイル/etc/nginx/server_certificates/ssl_pass_file.txtを作成する。

1
p4ssw0rd

NginXの設定

設定ファイル/etc/nginx/conf.d/default.confに以下を追記する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
server {
listen 443 ssl default_server;

## HTTPS化
ssl_certificate "/etc/nginx/server_certificates/server.crt";
ssl_certificate_key "/etc/nginx/server_certificates/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP;
ssl_prefer_server_ciphers on;
# パスワードファイルを読み込む
ssl_password_file /etc/nginx/server_certificates/ssl_pass_file.txt;

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

クライアント認証

クライアント認証に使用するファイルの保存場所を作成する

1
2
mkdir /etc/nginx/client_certificates
cd /etc/nginx/client_certificates

CA(Certification Authority)鍵を作成する

1
2
3
4
5
6
7
$ openssl genrsa -des3 -out ca.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
.........................................................................++++
......++++
e is 65537 (0x010001)
Enter pass phrase for ca.key:
Verifying - Enter pass phrase for ca.key:

CA(Certification Authority)証明書を作成する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ openssl req -new -x509 -days 365 -key ca.key -out ca.crt
Enter pass phrase for ca.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Shibuya-ku
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example, Inc.
Organizational Unit Name (eg, section) []:Development section
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

クライアント証明書を作成する

1
2
3
4
5
6
7
$ openssl genrsa -des3 -out user.key 4096
Generating RSA private key, 4096 bit long modulus (2 primes)
......................................................................................................................++++
.........................................................................................................................................................................................................++++
e is 65537 (0x010001)
Enter pass phrase for user.key:
Verifying - Enter pass phrase for user.key:

クライアント証明書に署名する

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ openssl req -new -key user.key -out user.csr
Enter pass phrase for user.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Tokyo
Locality Name (eg, city) []:Shibuya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example, Inc.
Organizational Unit Name (eg, section) []:Customer Support
Common Name (e.g. server FQDN or YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CSR(Certificate Signing Request)に署名する

1
2
3
4
5
$ openssl x509 -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out user.crt
Signature ok
subject=C = JP, ST = Tokyo, L = Shibuya, O = "Example, Inc.", OU = Customer Support
Getting CA Private Key
Enter pass phrase for ca.key:

PKCS(Public Key Cryptography Standards)を作成する

1
2
3
4
$ openssl pkcs12 -export -out user.pfx -inkey user.key -in user.crt -certfile ca.crt
Enter pass phrase for user.key:
Enter Export Password:
Verifying - Enter Export Password:

NginXの設定

設定ファイル/etc/nginx/conf.d/default.confに以下を追記する

1
2
ssl_client_certificate "/etc/nginx/client_certificates/ca.crt";
ssl_verify_client on;

最終的な設定ファイルは以下のようになる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
server {
listen 80 default_server;
listen [::]:80 default_server;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
server {
listen 443 ssl default_server;

## HTTPS化
ssl_certificate "/etc/nginx/server_certificates/server.crt";
ssl_certificate_key "/etc/nginx/server_certificates/server.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP;
ssl_prefer_server_ciphers on;
#
ssl_password_file /etc/nginx/server_certificates/ssl_pass_file.txt;

## クライアント認証
ssl_client_certificate "/etc/nginx/client_certificates/ca.crt";
ssl_verify_client on;

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

確認

クライアント証明書をインポートしていない場合

オレオレ認証なので–insecureオプションを付与してcurlコマンドを実行する。

1
2
3
4
5
6
7
8
9
$ curl --insecure https://localhost/
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.19.6</center>
</body>
</html>

サーバーログにはHTTPステータスコード400のエラーが記録される。

1
nginx01  | 192.168.64.1 - - [07/Mar/2022:02:57:45 +0000] "GET / HTTP/1.1" 400 237 "-" "curl/7.74.0" "-"

クライアント証明書をインポートした場合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ curl --insecure --key ./client_certificates/user.key --cert ./client_certificates/user.crt https
:/localhost/
Enter PEM pass phrase:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Certified</title>
<!--[if IE]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>

<![endif]-->
<style>
article, aside, dialog, figure, footer, header,
hgroup, menu, nav, section { display: block; }
</style>
</head>
<body>
<p>Hello World</p>
</body>
</html>

Nginxでパスワードのかかったpemファイルを使用する

パスワードファイルを準備する

/etc/nginx/server_certificates/ssl_pass_file.txtにパスワードを平文で記述する。

1
p4ssw0rd

Nginxの設定ファイル

pemファイルを使用する設定ファイルにssl_password_fileを追記する。

1
2
3
4
5
6
7
server {
listen 443 ssl;
...
ssl_password_file /path/to/password_file;
ssl_certificate_key /path/to/certificate_key.pem;
...
}

設定後に、Nginxをリロードする。

WordPress | 独自メニューを作成する

カスタムメニューを登録する

カスタムメニューを登録するには、register_nav_menus を使用する。

引数の配列要素のキーはメニューの識別 ID に使われ、値はメニューの表示名になる。

1
2
3
4
5
6
7
8
9
10
11
class MyCustomMenu
{
public function register_custom_menu() {
register_nav_menus(
array(
'custom_menu_slug' => 'カスタムメニュー',
)
);
}
}
add_action( 'init', array( new SiteRankingMenu(), 'register_custom_menu' ) );

カスタムメニューの内容を表示する

カスタムメニューに登録された内容をシンプルに表示してみる。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$menu_name = 'custom_menu_slug';

if ( ( $locations = get_nav_menu_locations() ) && isset( $locations[ $menu_name ] ) ) {
$menu = wp_get_nav_menu_object( $locations[ $menu_name ] );

$menu_items = wp_get_nav_menu_items($menu->term_id);

$menu_list = '<ul id="menu-' . $menu_name . '">';

foreach ( (array) $menu_items as $key => $menu_item ) {
$title = $menu_item->title;
$url = $menu_item->url;
$menu_list .= '<li><a href="' . $url . '">' . $title . '</a></li>';
}
$menu_list .= '</ul>';
} else {
$menu_list = '<ul><li>Menu "' . $menu_name . '" not defined.</li></ul>';
}

get_nav_menu_locations

機能

ナビゲーションメニューのアイテムを返す。

書式

1
<?php $items = wp_get_nav_menu_items( $menu, $args ); ?>

wp_get_nav_menu_object

機能

ナビゲーションメニューデータを取得する

書式

1
<?php $menu_item = wp_get_nav_menu_object(  $menu ); ?)>

ナビゲーションメニューが見つかった場合は。そのオブジェクトを返す。オブジェクトは以下のプロパティを持つ。

プロパティ名 データ型 説明
term_id int ID
name string 名前
slug string スラッグ
term_group グループ ID
term_taxonomy_id int タクソノミー ID
taxonomy string タクソノミー名
description string 説明
parent int 親カテゴリー ID
count int メニュー項目数
filter string