docker kubernetesの基本の基本

chapter 1,2

  1. dockerはLinuxマシンを想定して作られている。cgroupがLinuxの概念だからね。

  2. コンテナはイメージから作る

  1. コンテナはカーネルを持たない。が、カーネル以外のosの機能を持っている (本書ではそこを周辺部分と言っている)。カーネルはホストOSと共有する。だから軽い。

  2. コンテナはdocker Engineがあればどこでも動く

  1. コンテナはイメージとして書き出すこともできる!ここがsingularityのsifとは違うところだね。おそらくDockerはデフォルトでsingularityのsandboxと同じように、中身の改変が可能なのではないか?と思っている。まだ確信には至っていない。 –> そのとおりです。dockerはどの時点においても動いているコンテナをイメージとして書き出すことができます。 そのときに使うコマンドが、commitです。

  2. dockerでは物理的なマシンのディスクをマウントすることが可能。

  1. コンテナの外部のディスクに書き込むことで、ほかのコンテナとデータを共有することができる。
  1. dockerイメージはdocker hubからダウンロード可能

chapter3 dockerを使う

dockerの環境構築方法が書いてあるだけでした。お疲れ様です。

chapter4

  1. systemctl enable dockerでデーモンを自動起動させてください
  1. dockerコマンドの基本構文を抑えましょう
docker <上位コマンド> <副コマンド> <オプション>

<上位コマンド> == 何を <副コマンド> == どうする っていうのが結構しっくりきました。

<上位コマンド> : container, image, volume, network <副コマンド> : 上位コマンドごとに異なるけれども、 container : start, stop, create, run, rm, exec, ls, cp, commit image: pull, rm, ls, build

ちなみに、docker container run = docker (image pull + container create + container start)

  1. 主なオプションについて説明 –name : コンテナ名を指定 -p <ホストのポート番号 : コンテナのポート番号> : ポート番号をマッピング -v <ホストのディスク : コンテナのディレクトリ> : ディレクトリのマッピング –net=<ネットワーク名> : コンテナをネットワークに接続する。 -d : バックグラウンド実行 -i : コンテナに操作端末をつなぐ -t : 特殊キーを可能にする

ditをまとめて -ditとすることもよくある。

  1. コンテナ一覧の表示 docker ps
  1. ここからhandson(実際に手を動かしてやってみよう!!系)基本です!
# apache_ex1という名前の apacheサーバを image pullして、container createして、container startする。
docker run --name apache_ex1 -d httpd

# 動いているコンテナたちを確認 -a をつけると、停止している奴もみられる
docker ps (-a)

# ちなみに、-pオプションが使えるのはcreateのとき。つまり、
docker start apache_ex1 -p 8002:80
とかはできない。

# ということで通信してみようとなりました。
docker container run httpd -p 8002:80
でもいいのですが、練習もかねて、一連の流れを追ってみたいと思います。

# docker container runを順番にやってみる。imageはもととなる金型みたいなもの。クラスとインスタンスの違いのようなもの。そこから実際のコンテナを起動。ちなみにさっきhttpdはダウンロードしたので、下のやつはスキップされる
docker image pull httpd

# imageからコンテナをつくる。この時にいろいろ設定する必要がある。nameは絶対につけたほうがいい。というのも、
docker container create --name apache_ex2 -p 8002:80 httpd

# 起動。ここではあまりオプション選べません。
docker container start apache_ex2

# ブラウザでアクセスして確認してみましょう。

# ストップして、削除しよう
docker container stop & docker container rm apache_ex2

# 削除されていることを確認してみよう
docker ps -a

# 
  1. ここからは、いろんなタイプのコンテナを作成して、さらにコンテナに慣れよう!!的なあれですね。
# mysqlコンテナを立ててみよう!!

# imageのダウンロード
docker image pull mysql

# containerのcreate。eオプションでは環境変数を設定しています。
docker create --name mysql_test  -e MYSQL_ROOT_PASSWORD=myrootpass mysql

# containerのstart
docker start -dt mysql_test
  1. イメージの削除もしよう!!
# ホストに入っているイメージ一覧を次のコマンドで見られます。
docker image ls

# コンテナ名ではなく、イメージ名で削除します!!
docker image rm mysql httpd hello-world

chapter5 docker engine上で複数のコンテナを起動させてコンテナ同士で通信させる!!

まず、コンテナ同士でネットワークを構築できたのが驚きなのですが。できないと思っていたので。すごいねー。感激です。コンテナ同士で通信を許可するには、ネットワークを作らないとだめです。ネットワークの作り方をここでは説明する感じですかね。で、題材となるシステムは、Wordpressです!!wordpressは舐めたらあかんのですね。簡単に見えて、mysql + php + apachなんですよね。ということで、こいつらが通信にする方法を考えます。 ちなみになんだけど、俺が作ってるシステムもdocker使えば簡単に展開できるのではないか、と考えています。ワイドさんにも簡単に使えるようにしてあげないとだめですね。 (いや、今思ったのですが、僕のシステムは複数ノードにまたがって動いているものなので、Dockerだけじゃあだめなんですよ。kubernetesを使ってあげないと複数ノードにまたがるコンテナの管理はできません。)

# まずは、二つのコンテナが入るネットワークを作る
docker network wp_net1

# 作られたか確認
docker network ls

# mysqlコンテナを引っ張ってきて、作って、起動します
docker image pull mysql

sudo docker create --name mysql_net_ver --net wp_net1 -e MYSQL_ROOT_PASSWORD=myrootpass -e MYSQL_DATABASE=wordpressdb -e MYSQL_USER=wordpresskun -e MYSQL_PASSWORD=wkunpass mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password

sudo docker container start msyql_net_ver

# 続いて、wpコンテナを作る。この中には、wp + php + apachが入っているので、便利ですよと

sudo docker image pull wordpress

sudo docker container create --name wp_container --net=wp_net1 -p 8002:80 -e WORDPRESS_DB_HOST=mysql_net_ver -e WORDPRESS_DB_NAME=wordpressdb -e WORDPRESS_DB_USER=wordpresskun -e WORDPRESS_DB_PASSWORD=wkunpass wordpress 

sudo docker container start wp_container

# 8002晩ポートにアクセスするとみられます

さらに練習でredmineっていうのをインストールして使ってみます!!行きましょう!!

# network の作成
sudo docker network create redmine_net

# mysqlの準備
sudo docker image pull mysql

sudo docker create --name mysql_redmine --net=redmine_net -e MYSQL_ROOT_PASSWORD=myrootpass -e MYSQL_DATABASE=redmine_db -e MYSQL_USER=redmine_kun -e MYSQL_PASSWORD=rkunpass mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password

sudo docker start mysql_redmine

# redmineの準備
sudo docker image pull redmine

sudo docker container create --name redmine_main --network redmine_net -p 8002:3000 -e REDMINE_DB_MYSQL=mysql_redmine -e REDMINE_DB_DATABASE=redmine_db -e REDMINE_DB_USERNAME=redmine_kun -e REDMINE_DB_PASSWORD=rkunpass redmine

sudo docker container start 

大変面白かったです。気になる点としては、wordpressやredmineは -e REDMINE_DB_MYSQL=mysql_redmineとかの環境変数でどのコンテナと通信すればいいのかを判断しているようですが、さて、それがソフトウェアのほうからはどうやって見えているのかなっていう、そういう疑問です。ソフトウェア側でその環境変数を読み込むように既に設定してあるのですかね?

chapter6 応用的なコンテナの使い方をしよう

サーバーサイドエンジニア、セキュリティエンジニアであれば、dockerの知識はしっかりと身に着けてほしいところだと!!なるほど。なるほど。で、6章以降に説明する内容の概要をここで紹介していると。ハイハイ。サーバサイドエンジニアにとってはどれも必須の知識ですよと!!ハイハイ!!

コンテナとホスト間でファイルをコピーする

ボリュームのマウント

バインドマウントと、ボリュームマウントの二つがある。

コンテナのイメージ化

改造したコンテナをイメージにする方法は知っておきたいよね。singularityのsandbox -> sifへの変換に近い感じだと思うけど。

コンテナの改造

開発リーダなど、開発環境を配る側の人間はわかっていないと厳しいと

docker hubへの登録

docker compose

大量のコンテナを一発で起動できるようになるみたいで。これがわかると。ってことでやらないとね。 例えば、データベースとアプリを一緒に起動したいときとか。まあ、俺が作っているプロジェクトそのものだよね!!

kubernetes

複数台のサーバでコンテナを動かすときに使うオーケストレーションツール、だってさ。確かに、docker composeは複数台のサーバにわたってはできなさそうだもんね。一発起動とかはね。kubernetesを使うと一発起動ができるようになるんですかね??サーバにまたがっているやつでも。そうっぽいです。

コンテナとホストかんでファイルをコピーする。cp コマンドのdocker版ですね、簡単に言うと。

docker cp <copy source> <copy destination>

コンテナ側を指定するときは
container_name : /path/to/the/place
で指定しないとだめです。

apacheサーバのディレクトリにindex.htmlをおいて、確認してみましょう。

# apacheサーバの準備
sudo docker image pull httpd
sudo docker container create --name apache_container -p 8002:80 httpd
sudo docker container start apache_container

# La_keibaのindex.htmlをこぴー
sudo docker ~/hdd/La_keiba/src/front/index.html apache_container:/usr/local/apache2/htdocs

# これで、ホストの8002にアクセスするとindex.htmlにかわってますよーと。

ボリュームのマウント

そもそもボリュームとは何か?って話だが、ハードディスクあssdの区切られた1領域だとここで入っています。それってパーティションじゃね??と思ったんですが、パーティションはfdiskで作った後、まだ、ファイルシステムで初期化されていない状態だよね。つまり、 「ボリュームとは1個のファイルシステムを含むストレージ上の領域。」って感じかな。それでいいと思います。 で、ボリュームをマウントできると、dockerのコンテナには。便利やね。

sudo docker volume create <volume name>

バインドマウントは、

sudo docker container create -v </path/of/volume/> </mount/point/in/the/container>

実際に、バウンドマウントしてみるとこんな感じです。

sudo docker container create --name apache_container -p 8002:80 -v ~/hdd/La_keiba/src/front:/usr/local/apache2/htdocs httpd

コンテナのイメージ化

イメージの作成方法は2つありますと。 一つ目がcommitでイメージを買いだす方法。 もう一つが、Dockerfileでイメージを作る方法。

commitを使って書き出す方法は、作りこむ必要がある。まあこれはsingularityのsandboxをsifに変えるのに近いのかな。

docker commit <container_name> <output_image_name>

コンテナの改造

ここは結構気になるところです。というのも、改造してcommit出来たら、もうそれでどこでも実行できるようになるからですね。やりたいです。やはりosだけ入っているやるを持ってきて、その中でapt等を使っていろいろインストールすることも出きるっぽいですね。 いや、これはできるようになりたいです。

# osのみのコンテナをダウンロード
sudo docker image pull 

# startで始めるとなんか知らんがすぐ消えてしまう。なので、runで入らないとだめっぽい。
sudo docker run -it --name ubuntu_cont ubuntu /bin/bash

# 上のコマンドでシェルに入れる
root@4e64c06374a2

# htopをしても何も出てこない。ので、
apt upadte & apt install htop

# で、htopが使えるようになると

# ここで抜けてしまってもいいのか、わからないね。あー、抜けるとだめだね。psで見るともう死んでる。
で、docker start ubuntu_contをやるともうすぐ死んでしまうんだけど、

# これでノータイムでやれば死ぬ前に入れる
sudo docker start ubuntu_cont & sudo docker exec -it ubuntu_cont /bin/bash

しかも、加えた変更はちゃんと残っている。aptとかもちゃんと使える。なので、ここでコミットを確定させる。

# なるほど、createするときに -iオプションをつけるといい感じになる。これを覚えておいてください。

実際に、僕が作ったアプリとnodejsの実行環境をまとめたイメージをつくってみた!

試行錯誤してみます。


// osのみが入ったコンテナをpull
sudo docker image pull 

// ダウンロードできたかを確認
sudo docker image list

// コンテナを作る
sudo docker container create --name jc_data_checker -i ubuntu

// コンテナを起動する (-iオプションが大事)
sudo docker container start jc_data_checker

// 起動されたかを確認
sudo docker container ls

// コンテナの中に入る
sudo docker exec -it jc_data_checker /bin/bash

// 必要なパッケージのインストールなど!
apt update & apt install nodejs npm

// nodejsの設定など
npm install n -g
apt install wget
n stable
apt purge -y nodejs npm

// 一回ぬけてまた入る
exit
sudo docker exec -it jc_data_checker /bin/bash

// gitのインストール
apt install git

// private repositoryをgit cloneするためのkeyを生成 & githubに登録
ssh-keygen -t rsa & 登録

// githubにssh
ssh git@github.com

// privateリポジトリをgit clone


// bgのサーバなので、タイムゾーンをジャパンにかえる
tzselectがうまくいかない。.dockerenvはなかからゆーざが変えるものではないらしい。

// ちなみに、dockerにはrootしかいません。.profileとかも/root/にある
cd /root/

// なんか、.profileとかにTZ=Asia/Tokyoとか書き足してもだめ。やり直しですかね。

// createするときに-eでTZ=Asia/Tokyoを渡してみる
だめです。

なんか、osがubuntuの場合はTZを渡してもだめっぽいので、debianでやってみることにしました。

// イメージのプル
sudo docker image pull debina

// コンテナ作成、環境変数渡す
sudo docker container create --name jc_data_checker2 -i  -e TZ=Asia/Tokyo debian

// コンテナ起動
sudo docker start jc_data_checker2

// bashで中に入る
sudo docker exec -it jc_data_checker2 /bin/bash

// タイムゾーンの確認
date
Sat Aug 12 23:37:51 JST 2023
完璧です。

// 改めて必要なパッケージのインストールなど!
apt update & apt install nodejs npm

// nodejsの設定など
npm install n -g
apt install wget
n stable
apt purge -y nodejs npm

// 一回ぬけてまた入る
exit
sudo docker exec -it jc_data_checker /bin/bash

// gitのインストール
apt install git

// private repositoryをgit cloneするためのkeyを生成 & githubに登録
ssh-keygen -t rsa & 登録

// githubにssh
ssh git@github.com

// privateリポジトリをgit clone
git clone repository

// とりあえずここまでの内容をコミットして確定
exit
sudo docker commit jc_data_checker2 jc_data_checker_imagee

// イメージができたかを確認
sudo docker image ls

// 再び別の名前で作って起動
sudo docker container create --name jc_data -i jc_data_checker_imagee

// 起動&入る
sudo docker container start jc_data

// 普通にできていることを確認

// さっきポートのマッピングを忘れていたので、それをやってもいいかも、本番環境では。
sudo docker container create --name jc_data -p 8080:8080 -i jc_data_checker_image

// npmで必要なパッケージ類をインストール
package-lock.jsonとpackage.jsonがあるディレクトリにいって、
npm install
をするだけ。

// 一つだけ大事なこと
dockerコンテナは実はipアドレスを持っている。つまり、8080:8080でホストのポートをバインドしても、リクエストで届いたipがホストのipだと受け取らないこととかあるのよね。それを解消するために、どのipでも自分宛てに届いたものは処理するように、下のようにします。
    app.listen(port, '0.0.0.0', () => {
        console.log(`http server listening at http://0.0.0.0:${port}`);
    });

0.0.0.0ね。

0.0.0.0について

Binding to All Available Interfaces: When used in the context of binding a network service (like a web server) to an IP address, specifying 0.0.0.0 means that the service will listen on all available network interfaces or IP addresses on the host. In other words, the service will be accessible from any IP address that the host is reachable on. This can be useful when you want a service to be accessible from all devices within the network.

こんな感じです。

出来上がったイメージをファイルに落とし込んで別ホストに移して再びイメージとして使うまで!

// イメージを圧縮してファイルにする
sudo docker save -o jc_checker_image.tar jc_data_checker_comp

// scpでもなんでもいいからとりあえず移動

// 復元
sudo docker load -i jc_checker_image.tar

// あとはいつも通り起動するだけです。

singularityについて

sandboxとsifの違い

sandboxは編集可能なファイルになっている。編集可能というのは、ホームディレクトリ以外のディレクトリが母艦のでないやつがマウントされているということ。 つまり、/usr/local/とかが、osとは違うやつがマウントされているわけですね。sifももうなのかな?でもsifはapt installができないのよね。 sandbox -> sifへの変換が可能。

Dockerfileからsingularityコンテナを作る方法

研究で必要になったので、説明していきたいと思います。 2ステップです。Dockerfile -> docker image -> sifという流れで変換していきます。まずは、普通にDockerfileからdocker imageを作っていきたいと思います。

sudo docker build -t <出力コンテナイメージ名> <Dockerfileがあるディレクトリ(材料となるディレクトリ)>

このあと、必要なやつをどんどんインストールしていきます。かなりいろいろ必要でした。githubからソースをダウンロードしてきて、ビルドとかも必要でした。はい、まあ、こういうの結構楽しいんですけどね。

変更をコミットさせます。

sudo docker commit mgard_test pymgard_img

これで、mgard_testがpymgard_imgというイメージとして保存されたわけです。

次にやることは、docker imageからsingularity imageへの変換です。

singularity build my_container.sif docker-daemon://local/my_container:latest

実際に通ったのはこっちです。

sudo /usr/local/bin/singularity build pymgard.sif docker-daemon://pymgard_img:latest

はいおけー---!! これでできるみたいですね。docker containerはいくらでも改変可能ですが、singularity image fileは改変ができないのでdockerの時にできるだけたくさん変更を加えることをお勧めします。ちゅうことやな。

もともとあるdatabaseをdocker containerに移植したい

はい、まずは、ダンプしないといけないんだよね。さて、どうやってやるか。

mysqldump -u username -p source_database > backup.sql

だね。これが何か聞いてみると、次のような感じになります。

Yes, you're right! To migrate a MySQL database including its tables and data to another MySQL database, you can use the mysqldump command. mysqldump is a utility provided by MySQL that allows you to create a backup of a MySQL database in the form of SQL statements, which can then be used to recreate the database on another server.

ってかんじだねー。うん。で、backup.sqlを移植したいサーバにうつして、ってかんじだね。

次にやることがmysqlコンテナを作って、って感じなんだけど、mysqlのデータを永続化させるためにはちょっと工夫が必要なんです。基本的にmsyqlコンテナを使ってデータストレージを管理するのは良くないって話なんですけど、それでもどうしてもしたかったら、やり方があるみたいで、基本的にはバインドマウントではなく、volume mountをするという話になります。

jc_data_checkerをdocker-compose.ymlで一発起動できるようにする

ここですね。はい。動いているコンテナはたったの2つです。3つにすることもできますかね。いや、2つでいいですね。三つめはopenvpnサーバを考えていたのですが、まあなくてもいいかなって思ったのでね。 でですよ。 まあ、docker-compose.ymlを使って起動するわけですが。mysql-instanceもともに

で、外部のmysqlのデータを読み込んで動くmysqlコンテナの作り方なんだけど、まあサイトに書いてあるからそれを参考にしてみてくれ。 (https://girigiribauer.com/tech/20200713/)[ここ]に書いてある通りにやれば何も問題ないのだが、かなり詰まってしまった。というもの、 一回ボリュームを作ってmysql-data:/var/li/mysqlをマウントするとね、もうデータベースには変更が加えられないからなんだよね。何が言いたいかっていうと、一発で成功させないといけないということ。ここでだいぶ詰まってしまった。まあ仕方がない。結論から言うと、外部の.sqlファイルを起動時に読み込んでくれるmysqlコンテナは次のdocker-compose.ymlで作れる。

version: '3.8'

services:
  mysql:
    image: mysql:latest
    container_name: mysql-container
    environment:
      MYSQL_ROOT_PASSWORD: fantasic_fu
      MYSQL_DATABASE: jc_test
      MYSQL_USER: ray
      MYSQL_PASSWORD: mypassword
    volumes:
      - mysql-data:/var/lib/mysql  # Mount the named volume for data persistence
      - ./db/:/docker-entrypoint-initdb.d/
    command: --default-time-zone=+09:00
    restart: always

volumes:
  mysql-data:

説明しますね。 MYSQL_DATABASEを指定すると、コンテナが立ち上がるときにその名前のテーブルを作ってくれます。これはmysqlの公式がサポートしているコンテナで、そういう設定になっています。 次。/docker-entrypoint-initdb.d/にある.sqlファイルは起動時にmysqlに読み込まれるようになっています。ということで、mysqldumpで出したやつを./db/においておいて、それを-vでバインドマウントしています。って感じです。 次、volumeを/var/lib/mysqlにおいて、永続化しています。実際、docker-compose -f upで入って、INsert table(colum) value(val)で新しいデータを登録して、、docker compose -f downで一回終了させた後、また入ってみると、新たに登録したデータが残っていました。つまりデータが永続化されている、ということになります。これはすごいことです。

node.js環境が入っているdocker imageをDockerfileからつくる、のまき。

そうなんですよね。やっぱりDockefileはかけないとだめですわ。Dockerfileで利用可能な命令を書いておきますね。

  1. FROM : ベースイメージ
  2. MAINTAINER : メンテな。非推奨だから、入れなくていいよ。
  3. LABEL
  4. USER :実行時のユーザ
  5. EXPOSE :コンテナ実行時にリッスンするポートを指定。これ、-P 8080:8080とかとは違うのだろうか?
  6. COPY :ローカルにあるファイルをコンテナにコピー
  7. ADD : ローカルにあるtar.gzファイルの展開をして、ファイルをコンテナにコピーする
  8. RUN : コンテナ内でコマンドを実行する
  9. ENTRYPOINT : コンテナ起動時に実行するコマンド
  10. CMD : コンテナ起動時に実行するコマンドの引数
  11. WORKDIR :コマンドを実行する作業ディレクトリを指定

はい、でですね、基本コンテナは実行環境だけ提供していればいいんです。で、今僕がやっているのは、ソースコードごとコンテナの中に入ってる感じ。これは邪道ですね。どう考えても邪道。ありえんよ。ってはなしです。やり方としては、実行環境はいじらない。で、外部からソースコードを持ってきて、そこで実行するって感じです。でね、それをめちゃんこ簡単にしてくれるのがDockerfileって話なんですよ。そうなんです。ということでね。

FROM ubuntu:22.04

WORKDIR /root/La_scraper

# 必要なパッケージのインストール

# 最新のNODEJSインストール
RUN apt update && apt upgrade -y
RUN apt install nodejs npm unzip wget -y
RUN npm install n -g && n stable
RUN apt purge -y nodejs npm
RUN exec $SHELL

# xvfbのインストール & バックグラウンドで実行
RUN apt install xvfb -y
RUN Xvfb :1 -screen 0 '1280x1024x16' -ac &> /dev/null &

# chromeのインストール
RUN wget  https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

# 依存ライブラリも一緒にダウンロードしてくれる
RUN apt-get install -y ./google-chrome-stable_current_amd64.deb

# chromedriverのインストール
# RUN wget https://chromedriver.storage.googleapis.com/114.0.5735.90/chromedriver_linux64.zip
RUN wget https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/118.0.5993.18/linux64/chrome-linux64.zip
RUN unzip ./chromedriver_linux64.zip
RUN unzip ./chrome-linux64.zip

# ローカルからコピー
COPY ./package.json /root/La_scraper
COPY ./tanshou_to_santan_scraper.js /root/La_scraper
COPY ./package-lock.json /root/La_scraper

# npmで必要なモジュールをインストール
RUN npm install


# 必要な環境変数をここでエクスポートしてもいいですかね。
# いや、環境変数は実行時に渡すものですね。

# 以上で環境ができるはずです!

docker build -t <イメージ名>:<タグ> . ってやると、ビルドが始まります。ただね。えー、なんでかわからんが、これでは動かないんですわー--、ポンコツー-!!ってことで、まあ、今後頑張って、dockerの中でgoogle_chromeとseleniumを使ったscraperが同時起動できるように頑張っていきます。なにがげんいんなんでしょうかねー-。わからんですわ。

なんか、何やってもだめですね。意味が分かりません。どうすればいいのでしょうか。。。もうお手上げです!!わああああ!!!!って感じです!!!

Docker/Kubernetes 実践コンテナ開発入門