IT技術で仕事を減らしたい!

ITエンジニアのメモ+α

Docker nginxを使った静的なWebサイト

どうも、nippa です。

今回は Docker で静的サイトを公開したいと思います。

Docker を使う理由としては、

  • サービスのコード管理
  • 移行作業の簡略化
  • サービスのスケーラビリティの向上

など、数々のメリットがあります。

今回は、サービスのコード管理・移行作業の簡略化を目的とした、静的な Web サイトを 作成してみたいと思います。

コンテナの管理には docker-compose を利用します。

環境

  • macOS 10.15
  • docker version 20.10
  • docker-compose version 1.29
  • nginx 1.21

ディレクトリ構造

以下のようなディレクトリ構造を想定しています。

./docker_test/
 ┣ nginx/
 ┃   ┣ conf.d/default.conf
 ┃   ┗ dockerfile
 ┣ docker-compose.yml
 ┗ src/
     ┣ index.html
     ┗ 50x.html

srcには 静的な Web サイトのソースコードを配置して、それを nginx コンテナに読み 込む形を想定しています。

nginx の設定ファイルの作成

nginx.confについてはイメージ内のデフォルトのものを利用します。必要な方は設定し てください。

nginx/conf.d/default.confの設定に以下を書き込みます。この内容は nginx の初期設 定状態の内容です。

server {
    listen       80;
    server_name  localhost;

    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;
    }
}

静的な Web サイトの配置

srcに以下のindex.htmlファイルを配置します。

<!DOCTYPE html>
<html>
  <head>
    <title>My page</title>
  </head>
  <body>
    <h1>Welcome to my page!</h1>
  </body>
</html>

エラーページを配置します。エラーページは、nginx のデフォルトのものを利用します。

今回は nginx のデフォルトのエラーページを Github レポジトリの50x.htmlを取得し て利用します。

https://github.com/nginx/nginx/tree/master/docs/html

<!DOCTYPE html>
<html>
  <head>
    <title>Error</title>
    <style>
      html {
        color-scheme: light dark;
      }
      body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
      }
    </style>
  </head>
  <body>
    <h1>An error occurred.</h1>
    <p>
      Sorry, the page you are looking for is currently unavailable.<br />
      Please try again later.
    </p>
    <p>
      If you are the system administrator of this resource then you should check
      the error log for details.
    </p>
    <p><em>Faithfully yours, nginx.</em></p>
  </body>
</html>

docker-compose.yml の作成

今回は image を直接起動する形にします。docker-compose.ymlに以下を書き込みます 。

version: "3"
services:
  nginx:
    image: nginx:1.21-alpine
    container_name: nginx
    hostname: nginx
    ports:
      - 80:80
    volumes:
      - ./nginx/log:/var/log/nginx
      - ./nginx/conf.d:/etc/nginx/conf.d
      - ./src:/usr/share/nginx/html

コンテナの起動

docker-compose.ymlがある階層で以下のコマンドを実行してコンテナを起動します。

docker-compose up -d

コンテナの起動を確認します。

docker-compose ps

# 出力
Name               Command               State         Ports
-------------------------------------------------------------------
nginx   /docker-entrypoint.sh ngin ...   Up      0.0.0.0:80->80/tcp

ブラウザでhttp://localhostにアクセスすると 「Welcome to my page!」が表示されて いればコンテナの起動は成功です。

感想

いかがでしたでしょうか?docker、docker-compose を使うと簡単に静的サイトシステム の構築ができます。

SSL 認証を追加する場合は、少しややこしくなりますが、docker でも certbot を利用し て認証ページを公開することも可能です。

サーバに持っていけばすぐに公開できるので、試しに利用してみてください。

ではでは、また次回。

Git リモート先にsshの秘密鍵を引き継ぐ

どうも、nippa です。

リモートサーバに SSH 接続して、Githubソースコードを取得したいことがあると思います。

その際に、Github からのコード取得には ssh のみが許可されているの場合の対処法になります。

AWSGCPインスタンスを利用してサービスを提供する場合によくある状況だと思います。

Local の Github アクセス用の SSH 鍵を使って、インスタンス上にコードを clone する手順になります。

Github Docs にまとめられています。

Github Docs Using SSH agent forwarding

環境

ssh config の設定(macOS

${HOME}/.ssh/configにアクセスするサーバ情報を記載します。

オプションにForwardAgent yesを指定します。

Host test
     Hostname [IP or domain]
     User [username]
     IdentityFile [path of private key for server]
     ForwardAgent yes

ForwardAgent オプションを指定すると、指定した ssh key を ssh 接続先に引き継ぐことができます。

このとき、ssh 接続先には ssh key 自体は保存されません。

引き継ぐ秘密鍵の登録

ssh-addコマンドで引き継ぎ秘密鍵を指定します。

今回は githubssh 秘密鍵を指定します。

ssh-add [path of private key for github]

登録した鍵は

ssh-add -L

で確認できます。

ssh 先で github にアクセス

リモートのサーバに ssh ログインしたあとに

ssh -T git@github.com

# 表示
Hi [your account]! You've successfully authenticated, but GitHub does not provide shell access.

を行い、利用している github のアカウントが表示されることで確認できます。

登録した鍵の削除

以下のコマンドで登録した鍵をすべて削除できます。

ssh-add -D

感想

Githubクラウドサービスや VPS を利用することが多くなってきたこともあり、非常に便利になってきました。

ちょっとしたことを知っているだけで、作業が非常に効率に行えるようになりますが、その分、学習すべきことも増えています。

勉強すべきことはまだまだありますね。

ではでは、また次回。

Docker PostgreSQLの環境構築(その1)

どうも、nippa です。

テスト用の PostgreSQL 環境が必要になったのですが、VM で OS からインストールするのは時間がかかる、かつ

直接マシンにインストールすると後始末が面倒だということで、Docker を使うことにしました。

今回は Docker を利用して PostgreSQL サーバの環境を構築したいと思います。

環境

Docker のインストール

Docker のインストールは、公式サイトからインストーラーをダウンロードしてインストールします。

Docker 公式: Docker Desktop

詳しくはこちらの記事を確認ください。

Docker + PostgreSQL の構築

構築の流れは以下の通りです。

  1. PostgreSQL の Docker のイメージをダウンロード
  2. Dockerfile の作成

1. Docker のイメージをダウンロード

Docker のコアとなる image をダウンロードします。

docker image pull [image name]

#今回は ubuntu 20.04
docker image pull postgres:11-alpine

ダウンロードしたイメージの確認

docker image ls

# 結果
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
postgres                             11-alpine   283664b901ee   2 weeks ago    188MB

2. Dockerfile の作成

Dockerfile を作成します。

設定としては以下の通りです。

ここではファイル名はdockerfileとしています。

FROM postgres:11-alpine

# Time Zone
ENV TZ Asia/Tokyo

# Language
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8

3. Dockerfile からイメージ作成

Docker image をビルドします。

# イメージ名を指定して Docker imageのビルド
docker build -t [image name] .

# image名を postgres11-ja として作成
docker build -t postgres11-ja .

イメージが作成されていることを確認します。

docker images

REPOSITORY                           TAG       IMAGE ID       CREATED        SIZE
postgres11-ja                        latest    2fb039802ce9   2 weeks ago    188MB

postgres11-jaという名でイメージが作成されています。

4. 作成したイメージから container を起動

container nameimage nameを指定してコンテナを起動します。

起動時のオプションでパスワード、Listen ポートを指定します。

docker run --name postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgres

コンテナの起動を確認します。

docker ps

CONTAINER ID   IMAGE      COMMAND                  CREATED              STATUS              PORTS      NAMES
fb9bb88dab01   postgres   "docker-entrypoint.s…"   6 seconds ago   Up 4 seconds   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   postgres

上記の出力がされればコンテナ名:postgres で起動しています。

念の為、ポート状態を確認します。

lsof -i:5432

postgres がポート番号 5432 を利用していることを確認します。

5. PostegreSQL にアクセス

以下のコマンドで psql でデータベースにログインします。

psql -U postgres -d postgres -h localhost

実行するとパスワード起動時にPOSTGRES_PASSWORDで指定したパスワードでログインが可能となります。

感想

今回は docker で PostgreSQL のコンテナし、作成起動までを行いました。

VM で PosgreSQL を用意するよりはるかに簡単にサーバ環境を用意することができました。

次回は、docker-compose でもう少し便利な使い方をまとめたいと思います。

ではでは、また次回。

timesaving.hatenablog.com

timesaving.hatenablog.com

Docker はじめました

どうも、nippa です。

夏になりつつあるので、うちでも「Docker はじめました」の看板を出そうと思います。今更感はあります。

これまで、VMを使っていたのですが、以下の不満がありました。

  1. ホストPCのリソースをかなり消費する
  2. 立ち上げ、シャットダウンに時間がかかる
  3. 構築、再構築がめんどくさい

以下の場合にはVMをおすすめします。

  1. オンプレやクラウドインスタンスを利用する場合
  2. OSの設定の確認
  3. ミドルウェアの設定

アプリケーション開発の場合はDockerの方が遥かに便利であることに気づきました。

使い分けをした方が良いと思い、Dockerを利用することにしました。

環境

  • macOS 10.15
  • docker desktop 3.4

Dockerのインストール

今回はDocker destktopを利用しますが、基本的にコマンドラインでしか利用しない場合は、Homebrewでdockerをインストールしても問題ないと思います。

Docker desktopをインストール場合は、docker公式サイトからホストPCに合わせてダウンロードし、インストールしてください。

Homebrewでインストールする場合は、

brew install docker

イメージファイルのpull

dockerはイメージファイルを取得・作成して、そのファイルからコンテナを起動して実行します。

今回は、hello-worldのイメージファイルをpullします。

docker pull hello-world:latest

image:tagでpullするイメージとバージョンを指定することができます。

今回は最新をイメージファイルをpullしています。

pullしたイメージファイルの確認。

docker image ls

# 出力
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
hello-world              latest    d1165f221234   3 months ago   13.3kB

イメージの詳細の確認

イメージファイルの詳細は以下のコマンドで確認できます。

docker inspect hello-world

詳細が以下のように出力されます。

[
    {
        "Id": "sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726",
        "RepoTags": [
            "hello-world:latest"
        ],
        "RepoDigests": [
            "hello-world@sha256:9f6ad537c5132bcce57f7a0a20e317228d382c3cd61edae14650eec68b2b345c"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-03-05T23:25:25.230064203Z",
        "Container": "f5a78ef54769bb8490754e9e063a89f90cc8eee6a6c5a0a72655826e99df116e",
        "ContainerConfig": {
            "Hostname": "f5a78ef54769",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/hello\"]"
            ],
            "Image": "sha256:77fe0a37fa6ce641a004815f2761a9042618557d253f312cd3da61780e372c8f",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "19.03.12",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/hello"
            ],
            "Image": "sha256:77fe0a37fa6ce641a004815f2761a9042618557d253f312cd3da61780e372c8f",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 13336,
        "VirtualSize": 13336,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/78faf2fa6ec562c626b8a14e958d04a0ed9040abcac98299676a4d10e0e1c5b2/merged",
                "UpperDir": "/var/lib/docker/overlay2/78faf2fa6ec562c626b8a14e958d04a0ed9040abcac98299676a4d10e0e1c5b2/diff",
                "WorkDir": "/var/lib/docker/overlay2/78faf2fa6ec562c626b8a14e958d04a0ed9040abcac98299676a4d10e0e1c5b2/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:f22b99068db93900abe17f7f5e09ec775c2826ecfe9db961fea68293744144bd"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

コンテナの起動

イメージが取得できていることを確認したら起動になります。

docker run hello-world

# 出力
Hello from Docker!
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (amd64)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker ID:
 https://hub.docker.com/

For more examples and ideas, visit:
 https://docs.docker.com/get-started/

コンテナの状態の確認

起動しているコンテナを確認する場合は、以下のコマンドです。

docker ps

# 出力
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

停止しているコンテナも含めて表示する場合は、-aオプションをつけます。

docker ps -a

#出力
CONTAINER ID   IMAGE         COMMAND    CREATED          STATUS                     PORTS     NAMES
847a4df34e28   hello-world   "/hello"   52 seconds ago   Exited (0) 5 seconds ago             pensive_brown

hellow-worldイメージで起動したコンテナはExited (0)で正常終了していることがわかります。

コンテナの停止

hello-worldで起動したコンテナは、処理が終わると終了しますが、バックグラウンド起動したコンテナなどは、

docker stop [CONTAINER ID or NAMES]

で停止することができます。

コンテナの削除

停止しているコンテナの削除は、

docker ps -a

# 出力
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES
4bce8479da18   hello-world   "/hello"   2 minutes ago   Exited (0) 2 minutes ago             gallant_austin

コンテナIDまたはコンテナ名を確認して、

# docker rm [CONTAINER ID or NAMES]
docker rm 4bce8479da18

で削除できます。削除されていることを確認します。

docker ps -a

# 出力
CONTAINER ID   IMAGE         COMMAND    CREATED         STATUS                     PORTS     NAMES

コンテナの削除の完了です。

イメージファイルの削除

今あるDockerのイメージを確認します。

docker images
# または
docker image ls

# 出力
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE
hello-world              latest    d1165f221234   3 months ago   13.3kB

イメージを削除します。

# docker image rm [IMAGE ID or REPOSITORY]
docker image rm d1165f221234

削除されたことを確認。

docker images
# または
docker image ls

# 出力
REPOSITORY               TAG       IMAGE ID       CREATED        SIZE

感想

今夏はDockerのhello-worldを行いましたが、次回はもう少し実践向けの内容を書きたいと思います。

アプリケーション開発者にとってはDockerは必須の時代になるのかなと思っています。

更に、クラウド化が進めば進むほど、Dockerの優位性は高まるので、ぜひこれを機会にどんどん利用していきたいと思っています。

ではでは、また次回。

Python pyenv アップデートでpathの設定が変更

どうも、nippa です。

pyenv をアップデートしたら、Homebrew の python と confliction を起こしました。

その解決方法を記載しておきます。

原因はアップデートで python環境変数を指定しないといけなくなったことが原因のようです。

また anyenv を使って pyenv をインストールしていることもあり、少し複雑でした。

環境

  • macOS 10.15
  • anyenv 1.1.2
  • pyenv 1.2.27

pyenv のエラーについて

pyenv を anyenv の update プラグインでアップデートしたところ、ターミナルにログインするたびに以下のような warning が出力されるようになりました。

WARNING: `pyenv init -` no longer sets PATH.
Run `pyenv init` to see the necessary changes to make to your configuration.

ホームディレクトリの.zshrcに記載している

eval "$(pyenv init -)"

で pyenv の path の設定が行われなくなりました。

そのため、python が system(brew) の方に向いてしまっていました。

which python

# python path
/usr/local/bin/python

pyenv の path 設定の原因

pyenv アップデートによって、path の設定が変更になったようです。

path の設定方法が以前の変わっていました。

pyenv init

# (The below instructions are intended for common
# shell setups. See the README for more guidance
# if they don't apply and/or don't work for you.)

# Add pyenv executable to PATH and
# enable shims by adding the following
# to ~/.profile and ~/.zprofile:

export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

# Load pyenv into the shell by adding
# the following to ~/.zshrc:

eval "$(pyenv init -)"

# Make sure to restart your entire logon session
# for changes to profile files to take effect.

エラーの解決方法

pyenv を brew でインストールしている場合が、pyenv initの実行で出力される通りに.zprofile.zshrcに設定を書き換えれれば良いです。

#.zprofile に以下を記載
export PYENV_ROOT="$HOME/.pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

#.zshrcに以下を記載
eval "$(pyenv init -)"

anyenv で pyenv をインストールしている場合は、pyenv initで指定されている path ではないので、anyenv でインストールした pyenv の path を指定する必要があります。

anyenv のデフォルトのインストールであれば、以下のようになります。

export PYENV_ROOT="$HOME/.anyenv/envs/pyenv"
export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init --path)"

これで、エラーを解決できます。

感想

どうやら最近の変更によって起こる問題のようですね。

anyenv を使ってたのもあり少々困惑しましたが、アップデート後も問題なく python が使えています。

気軽に pyenv をアップデートしたら、設定が変更されていたので驚きましたが解決できたのでよしとしましょう。

ではでは、また次回。