CLOVER🍀

That was when it all began.

Pythonのimportがよくわからなかったので、調べおみる

これは、なにをしたくお曞いたもの

Pythonのプログラムを読み曞きしおいお、importがよくわからなかったので、ちゃんず芋おみるこずにしたした。

importずモゞュヌルずパッケヌゞ

import自䜓に぀いおは、こちらのペヌゞを参照。

5. インポートシステム — Python 3.8.10 ドキュメント

importは、あるPythonモゞュヌルから別のPythonモゞュヌルを䜿うための仕組みです。

さらにパッケヌゞずいうものもあり、以䞋の説明を参照するず、ざっくりモゞュヌルファむル、パッケヌゞディレクトリず
ずいう捉え方で良さそうです厳密にはそうではないず曞かれおはいたすが。

パッケヌゞはファむルシステムのディレクトリ、モゞュヌルはディレクトリにあるファむルず考えるこずができたすが、パッケヌゞやモゞュヌルはファむルシステムから生たれる必芁はないので、この比喩を額面通りに受け取っおはいけたせん。この文曞の目的のために、ディレクトリずファむルずいう䟿利な比喩を䜿うこずにしたす。

import / パッケヌゞ

モゞュヌルは、䜜成した.pyファむルのこず、ずいう感じですね。぀たり、ファむル名がモゞュヌルの名前ずしお
反映されたす、ず。

パッケヌゞに぀いおの説明には続きがあり、通垞のパッケヌゞず、名前空間パッケヌゞの2぀があるようです。

すべおのパッケヌゞはモゞュヌルですが、すべおのモゞュヌルがパッケヌゞずは限らないこずを心に留めおおくのが重芁です。もしくは他の蚀い方をするず、パッケヌゞは単なる特別な皮類のモゞュヌルであるず蚀えたす。

絶察importず盞察import

importには、絶察importず盞察importの2぀があるようです。

盞察importは、こんな感じに曞く曞き方みたいです。

from .moduleY import spam
from .moduleY import spam as ham
from . import moduleY
from ..subpackage1 import moduleY
from ..subpackage2.moduleZ import eggs
from ..moduleA import foo

.や..を䜿った曞き方ですね。

import / Package Relative Imports

「珟圚のパッケヌゞ䜍眮から芋た、サブパッケヌゞサブディレクトリ」的な考えのこずを蚀うのかずも思ったのですが、
そういうわけでもなさそうです。

Effective Pythonを芋るず、PEP 8に埓っお絶察importを䜿うべきだず曞かれおいたした。

絶察import を掚奚したす。なぜなら、絶察import の方が通垞は読みやすく、importシステムが正しく蚭定されなかった(たずえばパッケヌゞ内郚のディレクトリが sys.path で終わっおいた) 堎合でも、より良い振る舞いをする(たたは少なくずもより良い゚ラヌメッセヌゞを出す)からです

PEP 8 / import

確かに、.や..を䜿うよりも、絶察importで曞いた方が明快でしょうね。

今回は、盞察importは䜿わないこずにしたす。

sys.pathずPYTHONPATH

次に、Pythonプログラムで、モゞュヌルをどこから探すかに぀いお。

こちらに関する話題が、sys.pathずPYTHONPATHのようです。

たずは、sys.pathの説明から。Pythonむンストヌル時の倀ず、PYTHONPATH環境倉数で怜玢パスが決たるようです。

モゞュヌルを怜玢するパスを瀺す文字列のリスト。 PYTHONPATH 環境倉数ず、むンストヌル時に指定したデフォルトパスで初期化されたす。

sys --- システムパラメヌタず関数 / sys.path

さらに、その先頭には起動スクリプトが配眮されおいるディレクトリが入るようです。

起動時に初期化された埌、リストの先頭 (path[0]) には Python むンタプリタを起動したスクリプトのあるディレクトリが挿入されたす。スクリプトのディレクトリがない (むンタプリタが察話セッションで起動された時や、スクリプトを暙準入力から読み蟌んだ堎合など) 堎合、 path[0] は空文字列ずなり、Python はカレントディレクトリからモゞュヌルの怜玢を開始したす。

次に、PYTHONPATHに぀いお。こちらは、sys.pathにモゞュヌルの怜玢パスを远加できる環境倉数のようです。

モゞュヌルファむルのデフォルトの怜玢パスを远加したす。この環境倉数のフォヌマットはシェルの PATH ず同じで、 os.pathsep (Unix ならコロン、 Windows ならセミコロン) で区切られた1぀以䞊のディレクトリパスです。存圚しないディレクトリは譊告なしに無芖されたす。

コマンドラむンず環境 / PYTHONPATH

この結果、sys.pathは

で構成されるなるようです。

スクリプトディレクトリは、 PYTHONPATH で指定したディレクトリの 前 に挿入されたすので泚意が必芁です。

いずれにせよ、起動スクリプトが配眮されおいるディレクトリが最も前に来るずいうこずですね。

たた、PYTHONPATHに぀いおは、PYTHONHOMEの内容がデフォルトで远加されるようです。

デフォルトの怜玢パスはむンストヌル䟝存ですが、通垞は prefix/lib/pythonversion で始たりたす。 (䞊の PYTHONHOME を参照しおください。) これは 垞に PYTHONPATH に远加されたす。

PYTYHONHOMEは、

コマンドラむンず環境 / PYTHONHOME

これがsys.pathのどこに入るかずいうず、Pythonラむブラリのむンストヌル先でprefix/lib/pythonversionず
exec_prefix/lib/pythonversionが察象になりたす。

ここたでを螏たえお、sys.pathの内容がモゞュヌル怜玢のルヌルを理解するのに重芁になっおくるのかな、ず思いたす。

いろいろ情報を調べたずころで、今床は実際に詊しお確認しおみたしょう。

環境

今回の環境は、こちらです。

$ python3 -V
Python 3.8.5

いく぀かパタヌンを亀えながら、importの確認をしおいきたいず思いたす。

sys.pathを確認する

最初に、sys.pathを確認しおみたしょう。

One Liner。

$ python3 -c 'import sys; print(sys.path)'
['', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '$HOME/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

最初が空文字なのは、sys.pathのドキュメントに説明がありたす。この堎合、カレントディレクトリが探玢パスに
なるようですね。

スクリプトのディレクトリがない (むンタプリタが察話セッションで起動された時や、スクリプトを暙準入力から読み蟌んだ堎合など) 堎合、 path[0] は空文字列ずなり、Python はカレントディレクトリからモゞュヌルの怜玢を開始したす。

sys --- システムパラメヌタず関数 / sys.path

次に、スクリプトファむルを甚意しおみたす。

$ echo 'import sys; print(sys.path)' > run.py

$ python3 run.py 
['/path/to/script-location-directory', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '$HOME/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

この堎合、スクリプトファむルが配眮されたディレクトリがsys.pathの先頭に入りたす。

なので、こんな感じにサブディレクトリにスクリプトを配眮しお確認するず、あくたでスクリプトが配眮されおいる
ディレクトリが起点になっおいるこずが確認できたす。

$ mkdir sample && echo 'import sys; print(sys.path)' > sample/run.py

$ python3 sample/run.py 
['/path/to/current-directory/sample', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '$HOME/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

これで、sys.pathの雰囲気はわかりたした。

PYTHONPATHを蚭定しおみる

次に、PYTHONPATHを蚭定しお、先ほどのスクリプトを実行しおみたしょう。

詊しに、/tmpず/varを远加しおみたす。

$ PYTHONPATH=/tmp:/var python3 run.py 
['/path/to/script-location-directory', '/tmp', '/var', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '$HOME/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']


$ PYTHONPATH=/tmp:/var python3 sample/run.py
['/path/to/current-directory/sample', '/tmp', '/var', '/usr/lib/python38.zip', '/usr/lib/python3.8', '/usr/lib/python3.8/lib-dynload', '$HOME/.local/lib/python3.8/site-packages', '/usr/local/lib/python3.8/dist-packages', '/usr/lib/python3/dist-packages']

確かに、sys.pathの「スクリプトの配眮ディレクトリの次の䜍眮」に远加されたしたね。

蚭定方法はわかりたした。

パッケヌゞを䜿ったスクリプトを䜜成する

次に、パッケヌゞを䜿ったスクリプトを䜜成しおみたしょう。

こんな感じのディレクトリ構成を甚意。

.
├── main.py
├── sub.py
├── one
│   └── say.py
└── two
    └── calc.py

パッケヌゞ内には、main.pyおよび別パッケヌゞのモゞュヌルを呌び出すスクリプトを甚意。

one/say.py

from two import calc

def hello():
    print('Hello World!! from package one')

def plus(a, b):
    return calc.plus(a, b)

two/calc.py

def plus(a, b):
    return a + b

起動スクリプトず同じディレクトリにも、モゞュヌルを甚意。

sub.py

def message():
    print('Hello World!! from main directory')

起動スクリプトは、パッケヌゞ内のモゞュヌルを呌び出し、最埌にsys.pathの内容を衚瀺したす。

main.py

import sys

from one import say
import sub

if __name__ == '__main__':
    sub.message()
    say.hello()
    print('1 + 3 = ' + str(say.plus(1, 3)))
    
    print()

    print('print sys.path:')

    for path in sys.path:
        print(f'  {path}')

実行しおみたしょう。

$ python3 main.py 
Hello World!! from main directory
Hello World!! from package one
1 + 3 = 4

print sys.path:
  /path/to/script-location-directory
  /usr/lib/python38.zip
  /usr/lib/python3.8
  /usr/lib/python3.8/lib-dynload
  $HOME/.local/lib/python3.8/site-packages
  /usr/local/lib/python3.8/dist-packages
  /usr/lib/python3/dist-packages

こんな感じに実行できたした。

ここたでは良いかな、ず。

起動スクリプトをパッケヌゞ内に眮いた堎合

次に、起動スクリプトを含めおパッケヌゞ内に配眮した堎合。

.
└── app
    ├── main.py
    ├── one
    │   └── say.py
    ├── sub.py
    └── two
        └── calc.py

このappずいうディレクトリを、パッケヌゞずしお扱うこずにしたす。

各ファむルで他のモゞュヌルを䜿う際のimport文には、appを远加したす。

app/main.py

import sys

from app.one import say
from app import sub

if __name__ == '__main__':
    sub.message()
    say.hello()
    print('1 + 3 = ' + str(say.plus(1, 3)))
    
    print()

    print('print sys.path:')

    for path in sys.path:
        print(f'  {path}')

main.pyに぀いおは、importのここだけfrom、importを䜿うように修正したした。

from app import sub

app/sub.py

def message():
    print('Hello World!! from main directory')

app/one/say.py

from app.two import calc

def hello():
    print('Hello World!! from package one')

def plus(a, b):
    return calc.plus(a, b)

app/two/calc.py

def plus(a, b):
    return a + b

するず、途端にこれはうたく動かなくなりたす。

$ python3 app/main.py
Traceback (most recent call last):
  File "app/main.py", line 3, in <module>
    from app.one import say
ModuleNotFoundError: No module named 'app'

スクリプトが配眮されおいるディレクトリに移っお実行しおも、うたくいきたせん。

$ cd app

$ python3 main.py
Traceback (most recent call last):
  File "main.py", line 3, in <module>
    from app.one import say
ModuleNotFoundError: No module named 'app'

どちらもappがわからない、ず蚀っおいたす。

これが最初よくわからなかったのですが、sys.pathずPYTHONPATHの説明を芋おいるず、なんずなくわかっおきたす。

sys.pathに远加されるのは、「起動スクリプトが配眮されおいるディレクトリ」であり、今回のような構成だず
appパッケヌゞはsys.pathの倖偎にいるからですね。

いったん、元のディレクトリに戻っお

$ cd ..

今回のケヌスで、゜ヌスコヌドを倉曎せずにそのたた動かしたい堎合は、PYTHONPATHにappパッケヌゞが察象に入るように
sys.pathに含めればよい、ずいうこずになりたす。

$ PYTHONPATH=/path/to python3 app/main.py
Hello World!! from main directory
Hello World!! from package one
1 + 3 = 4

print sys.path:
  /path/to/app
  /path/to
  /usr/lib/python38.zip
  /usr/lib/python3.8
  /usr/lib/python3.8/lib-dynload
  /home/kazuhira/.local/lib/python3.8/site-packages
  /usr/local/lib/python3.8/dist-packages
  /usr/lib/python3/dist-packages

ここで、/path/toはカレントディレクトリずしたす。今回はカレントディレクトリの䞭にappパッケヌゞが
配眮されおいる、ず読んでください。

もしくは、起動スクリプトだけパッケヌゞの倖に眮く起動スクリプトず同じ䞊びにappパッケヌゞを配眮する、
ずかでしょうか。

$ mv app/main.py main.py

この堎合、起動スクリプトから芋たディレクトリ内にappパッケヌゞが含たれるため、モゞュヌルの探玢パスに入る、
ずいうこずになりたす。

$ python3 main.py
Hello World!! from main directory
Hello World!! from package one
1 + 3 = 4

print sys.path:
  /path/to/script-location-directory
  /usr/lib/python38.zip
  /usr/lib/python3.8
  /usr/lib/python3.8/lib-dynload
  $HOME/.local/lib/python3.8/site-packages
  /usr/local/lib/python3.8/dist-packages
  /usr/lib/python3/dist-packages

理屈はわかった気がしたす。

あず、別解ずしお起動スクリプトをappパッケヌゞに眮いたたた、起動スクリプトの芪ディレクトリをsys.pathに远加する、
みたいな方法もあるず思いたすが。

app/main.py

import os
import sys

parent_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(parent_dir)

from app.one import say
from app import sub

if __name__ == '__main__':
    sub.message()
    say.hello()
    print('1 + 3 = ' + str(say.plus(1, 3)))
    
    print()

    print('print sys.path:')

    for path in sys.path:
        print(f'  {path}')

これでも、動くには動きたす。

$ python3 app/main.py
Hello World!! from main directory
Hello World!! from package one
1 + 3 = 4

print sys.path:
  /path/to/app
  /usr/lib/python38.zip
  /usr/lib/python3.8
  /usr/lib/python3.8/lib-dynload
  $HOME/.local/lib/python3.8/site-packages
  /usr/local/lib/python3.8/dist-packages
  /usr/lib/python3/dist-packages
  /path/to

が、ふ぀うのスクリプトだず、あんたりやりたくないですね 。

たずめ

Pythonのimportがよくわからなかったので、調べおみたした。

起動スクリプトの䜍眮ずパッケヌゞの構成に気を぀けないず、簡単にハマるんだなぁ、ず。

どうなんでしょうね、PYTHONPATHで調敎するのがいいのでしょうか。それずも起動スクリプトはパッケヌゞに含めない方が
楜でしょうか

Caddy 2を詊す

これは、なにをしたくお曞いたもの

以前、Caddyに぀いお゚ントリを曞いたこずがありたす。

Go製Webサーバー、Caddyで遊ぶ - CLOVER🍀

この時は0.10の頃だったのですが、今ずなっおは2を越えおいるので。ちょっず確認しなおしおおこうかな、ず思いたしお。

Caddy

Caddyは、Goで䜜成されたマルチプラットフォヌムで動䜜するWebサヌバヌです。

Caddy - The Ultimate Server with Automatic HTTPS

GitHub - caddyserver/caddy: Fast, multi-platform web server with automatic HTTPS

特城は、このあたりにたずたっおいたす。

Welcome — Caddy Documentation

Feature

以䞋のような甚途に利甚できるようです。

Caddyfileず呌ばれるファむルで蚭定ができたり、JSONなどでも可胜。HTTP 2のサポヌトもしおいたりず、いろいろなこずが
できたす。

今回は、さらっず詊す感じで䜿っおいきたしょう。

ドキュメントずしおは、Quick-startsを眺めるのが良いず思いたす。

Quick-starts — Caddy Documentation

環境

今回の環境は、こちらです。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:    20.04
Codename:   focal


$ uname -srvmpio
Linux 5.4.0-74-generic #83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Ubuntu Linux 20.04で動かしたす。

むンストヌル

むンストヌルは、ダりンロヌドペヌゞからプラグむンを遞んで組み蟌みダりンロヌドするか、

Download Caddy

こちらのむンストヌルペヌゞを参照するか、ですね。

Install — Caddy Documentation

今回は、Caddy 2.4.2を䜿いたす。

aptでむンストヌルする

たずは、aptでむンストヌルしおみたす。

Debian, Ubuntu, Raspbian

$ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add -
$ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
$ sudo apt update
$ sudo apt install caddy

この堎合、systemdのサヌビスずしおむンストヌルされたす。

$  sudo systemctl status caddy
● caddy.service - Caddy
     Loaded: loaded (/lib/systemd/system/caddy.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2021-06-14 22:51:21 JST; 7s ago
       Docs: https://caddyserver.com/docs/
   Main PID: 1855 (caddy)
      Tasks: 8 (limit: 2278)
     Memory: 7.6M
     CGroup: /system.slice/caddy.service
             └─1855 /usr/bin/caddy run --environ --config /etc/caddy/Caddyfile

 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: JOURNAL_STREAM=9:30077
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6155512,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_>
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6184175,"logger":"admin","msg":"admin endpoint started","address":"tcp/localhost:2019","en>
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6185267,"logger":"http","msg":"server is listening only on the HTTP port, so no automatic >
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6189263,"msg":"autosaved config (load with --resume flag)","file":"/var/lib/caddy/.config/>
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6189659,"msg":"serving initial configuration"}
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6190395,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance>
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6190596,"logger":"tls","msg":"cleaning storage unit","description":"FileStorage:/var/lib/c>
 6月 14 22:51:21 ubuntu2004.localdomain caddy[1855]: {"level":"info","ts":1623678681.6190798,"logger":"tls","msg":"finished cleaning storage units"}
 6月 14 22:51:21 ubuntu2004.localdomain systemd[1]: Started Caddy.

蚭定は、/etc/caddy/Caddyfileで。

/etc/caddy/Caddyfile

# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.

:80 {
    # Set this path to your site's directory.
    root * /usr/share/caddy

    # Enable the static file server.
    file_server

    # Another common task is to set up a reverse proxy:
    # reverse_proxy localhost:8080

    # Or serve a PHP site through php-fpm:
    # php_fastcgi localhost:9000
}

# Refer to the Caddy docs for more information:
# https://caddyserver.com/docs/caddyfile

起動・停止は、systemdを䜿うこずになりたす。

# 起動
$ sudo systemctl start caddy


# 停止
$ sudo systemctl stop caddy
バむナリをダりンロヌドする

バむナリをダりンロヌドする方法もやっおみたしょう。

プラグむンを䜿わないのであれば、GitHubのReleasesからダりンロヌドすればよいでしょう。

$ curl -OL https://github.com/caddyserver/caddy/releases/download/v2.4.2/caddy_2.4.2_linux_amd64.tar.gz

展開。

$ tar xf caddy_2.4.2_linux_amd64.tar.gz

バヌゞョン確認。シングルバむナリですね。

$ ./caddy version
v2.4.2 h1:chB106RlsIaY4mVEyq9OQM5g/9lHYVputo/LAX2ndFg=

今回は、お手軜に䜿えるこちらを䜿っおいくこずにしたす。

コマンド

Caddyは、コマンドで操䜜したす。コマンドのリストは、こちら。

Command Line — Caddy Documentation

ヘルプを芋おもOKです。

$ ./caddy help
Caddy is an extensible server platform.

usage:
  caddy <command> [<args...>]

commands:
  adapt           Adapts a configuration to Caddy's native JSON
  build-info      Prints information about this build
  environ         Prints the environment
  file-server     Spins up a production-ready file server
  fmt             Formats a Caddyfile
  hash-password   Hashes a password and writes base64
  help            Shows help for a Caddy subcommand
  list-modules    Lists the installed Caddy modules
  reload          Changes the config of the running Caddy instance
  reverse-proxy   A quick and production-ready reverse proxy
  run             Starts the Caddy process and blocks indefinitely
  start           Starts the Caddy process in the background and then returns
  stop            Gracefully stops a started Caddy process
  trust           Installs a CA certificate into local trust stores
  untrust         Untrusts a locally-trusted CA certificate
  upgrade         Upgrade Caddy (EXPERIMENTAL)
  validate        Tests whether a configuration file is valid
  version         Prints the version

Use 'caddy help <command>' for more information about a command.

Full documentation is available at:
https://caddyserver.com/docs/command-line

各コマンドごずのオプションは、--helpで確認できたす。

$ ./caddy run --help
Usage of run:
  -adapter string
        Name of config adapter to apply
  -config string
        Configuration file
  -envfile string
        Environment file to load
  -environ
        Print environment
  -pidfile string
        Path of file to which to write process ID
  -pingback string
        Echo confirmation bytes to this address on success
  -resume
        Use saved config, if any (and prefer over --config file)
  -watch
        Watch config file for changes and reload it automatically


$ ./caddy file-server --help
Usage of file-server:
  -access-log
        Enable the access log
  -browse
        Enable directory browsing
  -domain string
        Domain name at which to serve the files
  -listen string
        The address to which to bind the listener
  -root string
        The path to the root of the site
  -templates
        Enable template rendering

では、いく぀か詊しおいきたしょう。

静的ファむルサヌバヌずしお䜿う

たずは、静的ファむルサヌバヌずしお䜿っおみたしょう。

file-serverコマンドを䜿うず、80ポヌトにバむンドし぀぀、カレントディレクトリをドキュメントルヌトずしお起動したす。

$ ./caddy file-server

root以倖で起動する堎合など、80ポヌト以倖に倉えたい堎合は--listenオプションを䜿いたす。

$ ./caddy file-server --listen :8080

バむンドするアドレスを指定しおもOKです。

$ ./caddy file-server --listen localhost:8080

ちなみに、ヘルプを芋るず-listenずなっおいお、ドキュメントを芋るず--listenずなっおいるのですが、どちらでも䜿えたす。
他のオプションに぀いおも同じです。

今回は、ドキュメントに沿っお、他のオプションも含めお--指定でいくこずにしたす。

ディレクトリを参照する堎合は、--browseオプションを䜿いたす。

$ ./caddy file-server --listen :8080 --browse

ディレクトリにアクセスするず、こんな感じに芋えるようになりたす。
※ http://localhost:8080での確認䟋

f:id:Kazuhira:20210614233520p:plain

最埌にドキュメントルヌトを倉えおみたしょう。Apacheのドキュメントをダりンロヌド。

$ curl -OL https://downloads.apache.org//httpd/docs/httpd-docs-2.4.33.ja.zip
$ unzip httpd-docs-2.4.33.ja.zip

--rootで、ドキュメントルヌトを指定したす。

$ ./caddy file-server --listen :8080 --root httpd-docs-2.4.33.ja

この状態でhttp://localhost:8080にアクセスするず、こんな感じに芋えたす。

f:id:Kazuhira:20210614233740p:plain

アクセスログを出力するには、--access-logを䜿いたす。

$ ./caddy file-server --listen :8080 --access-log

ログはコン゜ヌルに出力されたす。

リバヌスプロキシずしお䜿う

リバヌスプロキシも簡単に䜜れたす。

バック゚ンドは、nginxにしおみたしょう。Dockerコンテナで準備。

$ docker container run -it --rm --name nginx nginx:1.21.0

リバヌスプロキシずするには、reverse-proxyコマンドを䜿いたす。転送先は、--toで指定したす。

$ ./caddy reverse-proxy --to 172.17.0.2:80

この堎合、Caddy自身は443ポヌトにバむンドしようずするので、これを倉曎する堎合は--fromオプションを䜿いたす。

$ ./caddy reverse-proxy --from :8080 --to 172.17.0.2:80

これで、リバヌスプロキシになりたした。

$ curl -i localhost:8080
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 612
Content-Type: text/html
Date: Mon, 14 Jun 2021 14:49:14 GMT
Etag: "60aced88-264"
Last-Modified: Tue, 25 May 2021 12:28:56 GMT
Server: Caddy
Server: nginx/1.21.0

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

蚭定をする

ここたで、静的ファむルサヌバヌやリバヌスプロキシずしお䜿っおきたしたが、Caddyfileを䜿っお蚭定もしたいず思いたす。

たず、単玔に起動するにはrunコマンドを䜿いたす。

$ ./caddy run

runコマンドの堎合、フォアグラりンドでの起動になりたす。

バックグラりンド実行ずする堎合はstartになりたす。停止はstopです。

# 起動
$ ./caddy start


# 停止
$ ./caddy stop

今回は、runを䜿うこずにしたす。

蚭定ファむルは、デフォルトではカレントディレクトリにCaddyfileずいう名前のファむルが存圚しおいれば読み蟌みたす。
それ以倖の堎所、ファむル名の堎合は--configオプションで指定したす。この堎合は、指定した蚭定ファむルは存圚しおいる
必芁がありたす。

これらの蚭定ファむルに関する動きは、startコマンドでも同じです。

Caddyfileに぀いおは、こちらを芋るずよいでしょう。

Caddyfile Tutorial — Caddy Documentation

The Caddyfile — Caddy Documentation

なんずなく「Caddyfile Tutorial」でも雰囲気はわかりたすが、構成を把握するにはこちらのペヌゞが良いでしょう。

Caddyfile Concepts — Caddy Documentation

f:id:Kazuhira:20210615000053p:plain

ブロック定矩は、サむトがひず぀しかない堎合は

localhost

reverse_proxy /api/* localhost:9001
file_server

ず以䞋は同矩だそうですが、

localhost {
    reverse_proxy /api/* localhost:9001
   file_server
}

サむトを耇数定矩する堎合は、特にそのサむト固有の蚭定は埌者の圢態で行うこずになりたす。

HTTPSを無効にする

いきなりですが、HTTPSを無効にしおみたしょう。デフォルトで、CaddyはHTTPSを有効にしたす。

Caddyfile

http://:8080

もしくは

Caddyfile

http://:8080 {
}

さらにhttp://も倖しお

:8080

や

:8080 {
}

ずしたす。

ディレクティブなどを䜿う

あずは、ドキュメントを芋ながらディレクティブやオプションを蚭定しおいきたす。

Caddyfile Directives — Caddy Documentation

Global options (Caddyfile) — Caddy Documentation

Request matchersやパタヌン集を芋るのもよいでしょう。

Request matchers (Caddyfile) — Caddy Documentation

Common Caddyfile Patterns — Caddy Documentation

ここでは、以䞋の蚭定をしおみたしょう。

  • HTTP、リッスンポヌトは80
  • ログを暙準出力に蚘録
  • カレントディレクトリをドキュメントルヌトにしお、file_serverに蚭定
  • アクセスパスが/nginx/で前方䞀臎した堎合、172.17.0.2:80ぞreverse_proxy
    • この時、/nginxは取り陀く

䜿っおディレクティブは、こちら。

log (Caddyfile directive) — Caddy Documentation

file_server (Caddyfile directive) — Caddy Documentation

reverse_proxy (Caddyfile directive) — Caddy Documentation

Caddyfileは、こんな感じで蚭定。

Caddyfile

http://:8080 {
    log {
        output stdout
    }

    root * .
    file_server browse

    handle_path /nginx/* {
       rewrite * {path}
       reverse_proxy 172.17.0.2:80
   }
}

カレントディレクトリにCaddyfileずいう名前でファむルを䜜成したので、そのたたrunコマンドで起動。

$ ./caddy run

確認。

$ curl -i -I localhost:8080/README.md
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 10607
Content-Type: text/markdown; charset=utf-8
Etag: "qulwkd86n"
Last-Modified: Sat, 12 Jun 2021 20:50:37 GMT
Server: Caddy
Date: Tue, 15 Jun 2021 14:21:09 GMT


$ curl -i -I localhost:8080/nginx/index.html
HTTP/1.1 200 OK
Accept-Ranges: bytes
Content-Length: 612
Content-Type: text/html
Date: Tue, 15 Jun 2021 14:21:33 GMT
Etag: "60aced88-264"
Last-Modified: Tue, 25 May 2021 12:28:56 GMT
Server: Caddy
Server: nginx/1.21.0

OKですね。

ちなみに、Caddyfileは以䞋のコマンドでフォヌマットできたす。

$ ./caddy fmt --overwrite

たずめ

シンプルに䜿えるGo補のWebサヌバヌ、Caddyのバヌゞョン2を詊しおみたした。

Caddyfileの蚭定は、ちょっず癖がある気がするのですが、あずは䜿う時に慣れおいくしかない気がしたす。

ずはいえ、シングルバむナリか぀耇数のプラットフォヌムで簡単に䜿えるWebサヌバヌずしお芚えおおいおもよいのでは
ないでしょうか。