Dockerって?

今日はDockerについて話したいと思います。

 

 

Dockerについて

そもそもDockerってなんぞ?という話ですが、

Dockerはコンテナ仮想化技術を核としたオープンプラットフォームになります。

といってもよくわからないですね。

そうもそもVirtual Boxとかをつかった仮想化技術と何が違うの?

という話でもあります。

 

そこで、Dockerの最大の特徴であるコンテナ仮想化技術に関して話してから

Virtual Boxを使った仮想化との比較を話そうと思います。

 

コンテナとは?

Dockerとコンテナをセットで聞くことが多いと思います。

開発現場の事情から話始めると背景がわかりやすいかと思います。

 

よく見かけていた環境

 開発: 各々の個人PC(WindowsMac

     DBだけ共有サーバを使っていたりすることがある。

 本番: 環境で用意された環境

     アプリケーションとDBは別々のサーバを用意していることが多いはず

 

本番はWindowsサーバとかあったりもしますが、

私はLinux環境だったことが多かったです。

 

開発者は開発したあとに本番にデプロイしてリリースされることになります。

この過程にコストをかけないために様々な手段を講じていることが

多いのではないでしょうか?

また、開発環境とのOSの違いから生まれる動作の違いとかに悩まされたり

しなかったでしょうか?

 

ホストOSとは切り離した環境を用意して、開発をするために仮想化技術を使うと

考えられたわけです。

ホストOSとの隔離手段を「OSレベルの仮想化」といいます。

この種類の1つとして、

カーネルをホストを共有してプロセスとファイルシステムを隔離することを

コンテナ化技術」と呼ばれます。

 

 

Dockerは、コンテナを動かすためのDockerエンジンを提供しています。

開発者は、アプリケーションや設定ファイル情報をまとめたDockerコンテンを

Dockerイメージとして固めます。

本番はDockerエンジンを使えるようにすればDockerイメージを

置くだけで反映されるようになります。

 

Dockerコンテナを図にすると

f:id:ds_ricekun:20200505163905p:plain

てな感じです。

開発環境でPythonなどをいれたAPIやフロント用のコンテナは

Linuxのコマンドが使えます。

上の図では使えないように見えますが、仕組みとしては下図のようになります。

f:id:ds_ricekun:20200505165658p:plain

コンテナ内のプロセスは、

コンテナ内のコマンドやライブラリを参照してホストOSの

カーネルを使用します。

コンテナ内のコマンドやライブラリがLinuxのものになっているので

コンテナ内でLinuxのコマンドが利用できるようになっています。

ただし、使用できないコマンドは存在しています。

たとえば、viコマンドが使えません。

コンテナ内はゲストOSとまでは言えませんが、近しいものが入っています。

 

今回、私が作ったDocker環境をまとめると以下のようになります。

f:id:ds_ricekun:20200505170841p:plain

こうしてみるとDcokerにかなり助けられましたね。

Dockerなしでやるとすべてホスト機の中に

インストールする必要がありますから・・・・

 

仮想化マシンとの違いは?

こうしてみると仮想化マシンとの違いが気になるところです。

最大の違いはゲストOSの有無です。

DockerはゲストOSに近しいものが入っていますが、似て異なるものです。

何より起動の速さが全く違います。

初回のインストールも全然違かいます。

起動の速さは開発をする上では重要な問題です。

仮想環境の再起動などは、それほど多くの頻度ではないですが、

必要になります。

毎回数分もかかっていると1年間で2,3日分の稼働時間を

積もって損しているのではないでしょうか?

 

では、Dockerはデメリットはないのでしょうか?

当然あります。

1つは共有ディレクトリの遅さ問題です。

WindowやMacでDocker環境を構築し、ホストOSとディレクトリを共有すると

思いますが、この共有ディレクトリが原因で動作がおそくなってしまうことが

あります。

特にDB系で大量のinsertなどをすると現象が確認できるくらい起きることがあります。

2つ目はWindowsとの相性の悪さです。

WindowsでDockerを使うにはHyper-Vが必要です。

ですが、Hyper-Vを使うにはWindows Proである必要があります。

また、DockerはLinuxの利用が推奨されていることもあり、

いろいろと不整合的なことがおきることがあります。

 

さいごに

Dockerについて説明したした。

概要的な簡単なものですが、Dockerを知るきっかけになれたら幸いです。

 

 

 

Django ユーザ情報のカスタム

 

どうしてユーザもモデルをカスタムで用意する?

どのようなものを作りたいのかにもよる問題ではありますが、

サービスを考えたらユーザ情報を扱いたいと考えることは多いのでは

ないでしょうか?

個人で使うものだったそのようなものは不要ですが、

ゆくゆくはサービスを提供するとなったらユーザ情報をもつことは

必要です。

 

Djangoには、最初のmigrationしたときにユーザ情報用のテーブルを

用意しています。(このテーブルを以後ユーザモデルといいます)

ですが、models.pyの中を探しても該当するテーブルの記述がないので

ユーザ情報をカスタマイズしたいといったときに行いにくくなっています。

最大の問題は、

パスワード認証に使うものがusername固定になっています。

認証したいときにメールアドレスを使いたいときなどは

カスタムすることが必須になります。

 

私の個人的な意見ですが、

最初からカスタムユーザモデルを用意したほうがいいと思います。

Djangoは初期にテーブルを用意されているときに

ユーザモデルのテーブルの外部キーを張ってるテーブルが存在しています。

ある程度作った後に用意したりするといろいろと不整合が起きたりして

大変だと思います。

ですので、内容を変更しなくてもカスタム定義はしておいたほうが

あとで幸せだと思います。

 

カスタマイズ方法

AbstractUserかAbstractBaseUserか?

Djangoのユーザ情報をカスタマイズするには、

AbstractUserかAbstractBaseUserを継承したクラスにする必要があります。

これらを継承する特徴としては、

・AbstractUserの場合

 既存のユーザモデルを使用してカスタムする方法

 既存のユーザモデルらカラムをなくす場合には、削除したりする宣言をする

 必要がある。

・AbstractBaseUserの場合

 1からモデルを作るようになります。

 必要なカラムもすべて宣言する必要があります。

 

言葉で説明するとこんな感じです・・・・

一見するとAbstractUserでいいんじゃないの?

って気がしますよね!

あるのにわざわざ1から作る必要ないじゃん!

って思う人も少なくないはず

判断の大事なところは

 今回用意するユーザモデルをどうしたいか?

です。

AbstractUserで用意すると簡単に用意できるが、

元のユーザモデルを把握していないと

不要なカラムを作ってしまったりしてしまします。

 

AbstractBaseUserなら足しながら進められるが、

最初にある程度の設計が必要になります。

 

検索するとどっちがいいかという議論もあるようです。

私個人の意見ですが、

個人でいろいろ勉強や開発をするためならAbstractUserでいいと思います。

サービスで提供するならAbstractBaseUserをお勧めします。

サービスで提供→明確のユーザモデルの設計があるという感覚でいます。

今回は両方のやり方を書いていきます。

参考にしてもらえれば幸いです。

 

今後の方針

今回は両方試しますが、私はAbstractBaseUserで今後を進めます。

私の選択理由ですが、なんとなく設計方針が固まっていること

そして、せっかく勉強するなら制約がない方針でやりたいからです。

制約がないと理解しないと作れないから勉強んいなるやん!

という発想です。

 

今あるユーザモデルの確認

作業を始める前に今のユーザモデルを確認します。

どのカラムが必要なのか考えるためにも今の現状把握は大事ですね!

 

何も変更しないで作られるユーザモデルのテーブルは

「auth_user」になります。

モデルの詳細は別途機会を持ちたいと思っていますが、

Djangoは自動でテーブル名称を複数系にすることはありません。

構成は以下のものになります。

カラム名 データ型 補足
id int PK
password varchar(128)  
last_login datetime(6)  
is_superuser tinyint(1)  
username varchar(150) indexあり
first_name varchar(30)  
last_name varchar(150)  
email varchar(254)  
is_staff tinyint(1)  
is_active tinyint(1)  
date_joined datetime(6)  

usernameはユーザの氏名ではなくログインIDになります。

usernameには一意制約が設けられていました。

 違いがわかりにくいのはis_superuserとis_staffの違いです。

Djangoはコマンドを実行するとスーパーユーザを作ることができます。

デフォルトで用意されていることもあり、

ユーザモデルをカスタムする際には影響があります。

想定している権限管理として、

 ・一般権限

 ・スタッフ権限

 ・スーパーユーザ権限

の3つを想定しているようです。

 

 

手順

AbstractUserでもAbstractBaseUserでもやることは同じです。

1.Djangoプロジェクトにアプリケーションを追加する

 (すでにv1というアプリを追加しているので今回は省略します)

2.Managerを用意

2.models.pyに追加します。

3.settings.pyに追加します

になります。

2番目の手順の追加内容が継承するモデルによって変わります。

Managerは、先ほどすこし触れましたが、ユーザはコマンドで作ることができます。

ユーザモデルをカスタムするとこちらも影響を受けるので

用意する用意する必要があります。

 

今回すること

今回は、認証にusernameの代わりにemailを使って認証できる設定とします。

usernameなのですが、氏名ではなくログインIDが入る予定のカラムです。

emailで認証できるようにするのでこのカラムはなくしたいと思います。

また、権限管理がユーザモデル内にあってほしくないので

is_staff、is_superuserをなくします。

date_joinedも作成したことしか残らないので、created_atとupdate_atにしようと思います。

 

AbstractUser編

Mangerを用意するためにv1の中にmanagers.pyを用意します。

その中には、

from django.contrib.auth.base_user import BaseUserManager


class CustomUserManager(BaseUserManager):
    def create_user(selfemailpassword, **extra_fields):
        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(selfemailpassword, **extra_fields):
        extra_fields.setdefault('is_active'True)

        return self.create_user(email, password, **extra_fields)

とします。

BaseUserMangerがDjangoで用意しているユーザモデルのManagerです。

 

 AbstractUserを継承するmodels.pyは以下のようになります。

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils import timezone
from .managers import CustomUserManager

class CustomUser(AbstractUser):
    username = None
    is_superuser = None
    is_sutaff = None
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = 

    objects = CustomUserManager()

    class Meta:
        db_table="user"
        
    # 氏名をフルネームにして返す
    def get_full_name(self):
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def __str__(self):
        return self.email

 氏名をフルネームで出力したいこともあるだろうと思い、

そのメソッドまで書いています。

 

最後にsettings.pyに以下の内容を追記します。

# Application definition
AUTH_USER_MODEL = 'v1.User'

デフォルトで記述されていないので

お好みの場所に書いてください。

 

ここまでできたら、

APIコンテナに入って、以下のコマンドを実行します。

python manage.py makemigrations
python manage.py migrate

 

作業前に一度マイグレーションしているとmakemigrationsはできると思いますが、

migrateでエラーになると思います。

そのときは、

v1/migrationsの中にある_init_.py以外を削除します。

DBのテーブルもすべて削除します。

この状態でmakemigrationsからやり直してください。

 

migrateまで実行できたらDBに確認しに行きましょう。

 models.pyで

    class Meta:
        db_table="user"

と書いているので作成するテーブル名を指定しているので

確認するテーブルは「user」になります。

試しにユーザを作ってみましょう。

APIコンテナ内で

python manage.py createsuperuser

 になります。

作ったユーザを確認すると

パスワードはハッシュ化されています。

created_atやupdate_atは日本時間ではなくUTC(標準時間)で入ります。

これは、標準時間ならどの時間にも変換することが可能だからです。

 

ここまでくればユーザモデルのカスタマイズは完了です。

 

AbstractBaseUser編

Managerに関してですが、同じで大丈夫ですので再利用します。

models.pyが大きく変わります。

from django.db import models
from django.contrib.auth.models import PermissionsMixin, UserManager
from django.contrib.auth.base_user import AbstractBaseUser
from django.utils import timezone

from .managers import CustomUserManager
# ユーザ情報
class Accout(AbstractBaseUserPermissionsMixin):

    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=30blank=True)
    last_name = models.CharField(max_length=150blank=True)

    is_active = models.BooleanField(
        default=True,
        help_text=_(
            "利用状況フラグ 1:利用中 0:利用不可"
        ),
    )

    created_at = models.DateTimeField(default=timezone.now)
    updated_at = models.DateTimeField(auto_now=True)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = 

    class Meta:
        db_table="accout"

    # 返値にフルネームを作成して返す
    def get_full_name(self):
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

 

今回はAccountにしているのでsettings.pyは

# Application definition
AUTH_USER_MODEL = 'v1.Account'

になります。

 

あとは 

python manage.py makemigrations
python manage.py migrate

を実行してマイグレーションを実行しましょう。

 

確認のために

python manage.py createsuperuser

を行って、Accountテーブルにレコードが増えているか確認しましょう。

 

開発環境を作る part3

 

今回用意したgit

  front : https://github.com/dsrice/base-angular/tree/step1

  docker: https://github.com/dsrice/base_docker/tree/step3

はじめに

part3もかかってしましましたが、

環境つくりも今回で最後です。

いろいろ触ったときにupdateしていくかもしれませんが、

始めるには必要な環境はとりあえず揃います。

 

今回はフロントサイドになるAngularを使えるようにしたコンテナの追加です。

今まではいろいろと面倒なことも多かったですが、

今回はシンプルだと思います。

 

手順1 フロントサイドコンテナの追加

api側今回編集しないので省略しますが、新しくフロント関連のを追記します。

  ┣ーーbase_docker
  ┃  ┣ーーcontents
  ┃    ┣ーーfront(このフォルダとその配下追加)
  ┃       ┃      ┗ーーDockerfile
   ┃   ┣ーーapi
  ┃  ┃  ┗ーーmysql
  ┃  ┃     ┣ーーDockerfile
  ┃  ┃     ┗ーーconf.d
  ┃       ┃              ┗ーーmy.conf
  ┃    ┗ーーdocker-compose.yml
  ┃ 
  ┗ーーbase-django
 
  ┃ 
  ┗ーーbase-angular(追加しなくてもdocker起動時に追加されます)

 

docker-compose.ymlの追記内容は以下のようになります。

 
version'3'

services:
  base_db:
    build./contents/mysql
    container_namebase_mysql
    restartalways
    environment:
      MYSQL_ROOT_PASSWORDroot
      MYSQL_DATABASEblog
      MYSQL_USERblog
      MYSQL_PASSWORDblog
      TZ'Asia/Tokyo'
    command--innodb-use-native-aio=0
    volumes:
      - ./cache/db/ :/var/lib/mysql
      - ./contents/mysql/conf.d :/etc/mysql/conf.d/
      - ./log/mysql :/var/log/mysql
    ports:
      - 33306:3306
 
# ここから追加
  front:
    build./contents/front
    container_namebase-front
    ports:
      - "4200:4200"
    volumes:
      - "../base-angular :/basefront"
    ttytrue
# ここまで追加        
 
  api:
    build./contents/api
    container_namebase-api
    restartalways
    ports:
      - "8000:8000"
    commandsh -c "sleep 5; python baseapi/manage.py runserver 0.0.0.0:8000"
    volumes:
      - "../base-django :/base-api"
      - "./contents/server :/code" 
    depends_on:
      - base_db
    ttytrue
        
  phpMyAdmin
    container_namebase_phpmyadmin
    imagephpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=base_mysql
      - PMA_USER=blog
      - PMA_PASSWORD=blog
    ports:
      - 8080:80
 
Dockerfileの内容は以下のものになります。
FROM node:12.16.1

RUN npm install -g @angular/cli

RUN mkdir /basefront
WORKDIR /basefront

EXPOSE 4200
*ここではVersion指定しています。
動作確認時はVersion9.1.4が最新でしたが、何をやっても新規作成ができませんでした。
どうにか突破しようとしましたが、厳しい感じでした。
状況を見守って外せればと思っています。
 
追加ができたら、base_dockerフォルダまで移動して
docker-compose build
 を実行してください。
 
buildが実行出来たら
docker-compose build
 を実行して、
新しく「base-front」というコンテナが動いていることを確認しましょう。
 

手順2 angulerのアプリの作成

次に開発するためのangularプロジェクトを作ります。

base-frontコンテナに入ります。

docker exec -it base-front /bin/bash
 
コンテナ内に入ったら
ng new front
で新しいAngularアプリを用意しましょう。
 
アプリ作成時に2つほど質問されます。
私は以下の設定が実行しました。
お好みで実行してもらえればと思います。
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS
 
Angular9の環境だとng newだけでアプリを作成すると
エラーが発生することがあります。
コンテナを再起動したりすると問題なく作成できるようになったりと
なかなかの謎の状況でした。
 
無事に作成ができたら
ng serve --host=0.0.0.0
 に起動してください。
ホストOSのブラウザで
にアクセスしてください。
成功すると以下のページが表示されます。
 

f:id:ds_ricekun:20200503125724p:plain

 
ここまで来たらほぼ終了です。
最後にdocker-compose.ymlにcommandを追加して
コンテナを起動したときにアプリを起動するようにしましょう。
 
version'3'

services:
  base_db:
    build./contents/mysql
    container_namebase_mysql
    restartalways
    environment:
      MYSQL_ROOT_PASSWORDroot
      MYSQL_DATABASEblog
      MYSQL_USERblog
      MYSQL_PASSWORDblog
      TZ'Asia/Tokyo'
    command--innodb-use-native-aio=0
    volumes:
      - ./cache/db/ :/var/lib/mysql
      - ./contents/mysql/conf.d :/etc/mysql/conf.d/
      - ./log/mysql :/var/log/mysql
    ports:
      - 33306:3306
    
  front:
    build./contents/front
    container_namebase-front
    ports:
      - "4200:4200"
    commandng serve --host=0.0.0.0(追加)
    volumes:
      - "../base-angular/front :/basefront"(修正)
    ttytrue
        
  api:
    build./contents/api
    container_namebase-api
    restartalways
    ports:
      - "8000:8000"
    commandsh -c "sleep 5; python baseapi/manage.py runserver 0.0.0.0:8000"
    volumes:
      - "../base-django :/base-api"
      - "./contents/server :/code" 
    depends_on:
      - base_db
    ttytrue
        
  phpMyAdmin
    container_namebase_phpmyadmin
    imagephpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=base_mysql
      - PMA_USER=blog
      - PMA_PASSWORD=blog
    ports:
      - 8080:80
 
私の環境だけかもしれませんが、Angularの立ち上がりが遅かったです。
時間がかかるものだとして割り切って使うことにします。
 

補足(The Schematic workflow failed.See above. エラー)

ng new をしたときになぜかエラーになることがある

動作確認中によく起きたので、対応をまとめておく

出たエラー内容で最も多かったのが、

npm ERR! code ENOENT
npm ERR! syscall rename
npm ERR! path /basefront/basefront/node_modules/.staging/@schematics/update-b00fae6d
npm ERR! dest /basefront/basefront/node_modules/@schematics/update
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, rename '/basefront/basefront/node_modules/.staging/@schematics/update-b00fae6d' -> '/basefront/basefront/node_modules/@schematics/update'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! A complete log of this run can be found in:
npm ERR! /root/.npm/_logs/2020-05-03T02_08_25_658Z-debug.log
✖ Package install failed, see above.
The Schematic workflow failed. See above.

 

エラーがでたあとに状況を確認すると

node_modules / .stagingフォルダの中に対象のエラーを出力したモジュールが残っていた。

対応手順は、

①.stagingフォルダ内に残っているものをすべて削除します。

②コンテナに入り、Angularアプリのフォルダで

(私の場合は、basefront/basefront)

npm i

を実行します。

 

発生する理由は調べてもよくわかりませんでした。

この方法でもうまくいく時といかない時がありましたので原因が

わからないので完璧な対応にはなりませんでした。

 

それでもうまくいかないときは

node_modulesフォルダの中身をすべてなくして

npm i

を実行します。

 

 

 

開発環境を作る parat2

 

今回の作成したものへのGit

 Docker

  https://github.com/dsrice/base_docker/tree/step2

 API

  https://github.com/dsrice/base-django/tree/step1

はじめに

今回は、前回作った環境に新しくPythonで作るAPIサーバのコンテナと

フロントサイドをAngularで作るWebサーバのコンテナを

前回作成したdocker環境に追加していきます。

 

作業環境

 ・Windows10 Pro

   ・Docker Desktop on WIndows

 

作業Git

 Dockerの設定関連

 Webサーバ

   APIサーバ

 

APIサーバの用意

最初に書きましたが今回はPythonで作ります。

採用するフレームワークDjangoです。

Djangoを採用する理由ですが、

 言語はPythonと決めていたので採用がもっとも多いDjangoにしたというだけです。

細かいところはやりながら勉強します。

 

手順1 APIサーバのコンテナを用意する。

なにはともあれまずPythonをインストールしたコンテナを用意する必要があります。

docker-compose.ymlを以下の内容に編集します。

version'3'

services:
  base_db:
    build./contents/mysql
    container_namebase_mysql
    restartalways
    environment:
      MYSQL_ROOT_PASSWORDroot
      MYSQL_DATABASEblog
      MYSQL_USERblog
      MYSQL_PASSWORDblog
      TZ'Asia/Tokyo'
    command--innodb-use-native-aio=0
    volumes:
      - ./cache/db/ :/var/lib/mysql
      - ./contents/mysql/conf.d :/etc/mysql/conf.d/
      - ./log/mysql :/var/log/mysql
    ports:
      - 33306:3306
    
  api:
    build./contents/api
    container_namebase-api
    restartalways
    ports:
      - "8000:8000"
    volumes:
      - "../base-django :/base-api"
      - "./contents/server :/code" 
    depends_on:
      - base_db
    ttytrue
        
  phpMyAdmin
    container_namebase_phpmyadmin
    imagephpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=base_mysql
      - PMA_USER=blog
      - PMA_PASSWORD=blog
    ports:
      - 8080:80
 
さらにAPIコンテナのためにcontentsフォルダをにも新しく追加します。
追加後のフォルダ構成は以下のようになります。
 
  ┣ーーbase_docker
  ┃  ┣ーーcontents
  ┃  ┣ーーapi(このフォルダとその配下追加)
  ┃       ┃     ┃  ┣ーーDockerfile
  ┃       ┃     ┃  ┗ーーrequirement.txt
  ┃  ┃  ┗ーーmysql
  ┃  ┃     ┣ーーDockerfile
  ┃  ┃     ┗ーーconf.d
  ┃       ┃              ┗ーーmy.conf
  ┃    ┗ーーdocker-compose.yml
  ┃ 
  ┗ーーbase-django(追加しなくてもdocker起動時に追加されます)
 
 contentsフォルダ内に配置するDockerfileは、以下の内容のものになります。 
RUN mkdir /code
RUN apt-get update
WORKDIR /code
ADD requirement.txt /code/
RUN pip install -r requirement.txt
ADD . /code/
WORKDIR /base-api

EXPOSE 8000
 requirement.txtはコンテナをbuildするときにファイルの中にあるモジュールをpip installで取得するようになります。コンテナ内でpip installすることは可能ですが、コンテナが再起動するたびに初期化されます。開発をしているとコンテナの再起動をするケースとかは珍しくないのでbuildしたコンテナイメージはインストール済みにしてあることがおすすめです。 今回用意したrequirement.txtの内容は
Django
psycopg2
djangorestframework
django-filter
mysqlclient
 になります。installするモジュールのVersion指定も可能です。今は指定する必要がないので最新版で動けばいいと思います。 

手順2 djangoのアプリを用意する。 

base_apiはホストOSとコンテナ間の共有ディレクトリになります。

このため、docker-compose upすることでディレクトリがない場合は作られます。

共有するディレクトリはdocker環境の外のディレクトになります。

このようにしている理由は、

dockerの環境だけをgit管理したかったです。

apiapiだけでgit管理をしたく、混在しているとgit管理がしにくそうだったからです。

 
コンテナが起動していなかったら
「docker-compose up」してコンテナを起動してください。
 
 
base-apiコンテナの中に入ります。
新しくコマンドプロンプトを立ち上げてください。
必要なコマンド

 

docker exec -it base-api /bin/bash

 

になります。
このコマンドはコンテナに入るときに使用するコマンドになります。
base-apiの部分を入りたいコンテナの名称に変更することで別のコンテナに入ることができます。
 
コンテナに入ったら

 

django-admin.py startproject baseapi
 を実行してください。
実行するとDjangoプロジェクトとしてbaseapiができます。
プロジェクト名に決まりはないですが、
ここではbaseapiがプロジェクト名としていろいろなものを書いていきます。
その点に注意していただけば問題ないです。
さらにアプリケーションも追加しておきます。
追加時は作成したプロジェクト内に移動してから実行する必要があります。
cd baseapi
python manage.py startapp v1
 

手順3 djangoのアプリを設定を変更する。

ホストOS側からdjangoプロジェクトの設定を変更します。

主な変更点は、

 ・RESTfull APIとするつもりなので設定を追加する。

 ・DBはデフォルトSQLiteなのでMysqlに変更する。

の2点です。

 

RESTful API対応

 初期状態ではRESTful APIをするには設定が足りていないので追加します。

本来は、モジュールの追加installが必要なのですが、

すでにrequirement.txtに追記しているので今回は不要になります。

必要なものは

 ・djangorestframework
 ・django-filter

の2つになります。

 

設定を追加するところは

base-api/baseapi/setting.py

アプリケーションの追加も行っています。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',(追加)
    'v1',(追加)
]

 

MySQL対応

先ほどのファイルにさらに追加を行います。

必要なモジュールはインストール済みです。

必要なものは

 ・mysqlclient

のみです。

 

base-api/baseapi/setting.py

DATABASES = {
  'default': {
    'ENGINE''django.db.backends.mysql',
    'NAME''blog',
    'USER''blog',
    'PASSWORD''blog'
    'HOST''base_mysql',
    'PORT''3306',
    'OPTIONS': {
        'charset''utf8mb4',
    },
  }
}

デフォルトでは、SQLiteへの接続設定が記載されています。

ここでは残していませんが、残したい方はコメントアウトでも可能です。

ポイントportの指定です。

docker-compose.yml内では、ポート転送の設定を入れています。

しかし、このポートはホストOSとMySQLコンテナ間の転送設定です。

MySQLコンテナとAPIコンテナ間はホストOSを経由するわけではないので

3306で通信できるようになります。

 

設定は以上です。

正常に接続できるか確認のため、APIコンテナに入ります。

入ったらmigrationを実行します。

docker exec -it base-api /bin/bash

cd baseapi

python mange.py migrate

MySQLコンテナとの通信が問題がなければDjangoが用意する

初期テーブルが作成されます。

 

テーブルが作成されたらサーバを起動させてみましょう。

python mange.py runserver 0.0.0.0:8000

 

ホストOSのブラウザから

http://localhost:8000」でアクセスしてください。

問題がなければ、下の画面が表示されます。

f:id:ds_ricekun:20200429224753p:plain

 ここまで来たらほぼ終了です。
 
今のままでもいいのですが、
サーバ起動のためにはコンテナ内に入る必要があります。
少々面倒だと思うので最後にdocker-compose.ymlに追記します。
version'3'

services:
  base_db:
    build./contents/mysql
    container_namebase_mysql
    restartalways
    environment:
      MYSQL_ROOT_PASSWORDroot
      MYSQL_DATABASEblog
      MYSQL_USERblog
      MYSQL_PASSWORDblog
      TZ'Asia/Tokyo'
    command--innodb-use-native-aio=0
    volumes:
      - ./cache/db/ :/var/lib/mysql
      - ./contents/mysql/conf.d :/etc/mysql/conf.d/
      - ./log/mysql :/var/log/mysql
    ports:
      - 33306:3306
    
  api:
    build./contents/api
    container_namebase-api
    restartalways
    ports:
      - "8000:8000"
    commandsh -c "sleep 5; python baseapi/manage.py runserver 0.0.0.0:8000"(追加)
    volumes:
      - "../base-django :/base-api"
      - "./contents/server :/code" 
    depends_on:
      - base_db
    ttytrue
        
  phpMyAdmin
    container_namebase_phpmyadmin
    imagephpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=base_mysql
      - PMA_USER=blog
      - PMA_PASSWORD=blog
    ports:
      - 8080:80
APIコンテナに新しくcommandを追加しました。
これでコンテナ起動時にサーバ起動まで行うようになります。
migrationとかは起動時に行わずに、コンテナに入る想定です。
これは開発していくなかで面倒だったりしたら追記すればいいと思います。
コマンドにsleepがある理由ですが、docker-compose upしたときにMySQLコンテナを先に起動するようにしてはありますが、
APIコンテナのコマンド実行が早すぎて起動に失敗するケースがあります。
なので実行を少し待つ必要があるのでこのようにしています。
 
追加したら
「docker-compose up」
(起動していたら一度「docker-compose down」で落としてください)
で立ち上げてください。
 

ホストOSのブラウザから

http://localhost:8000」でアクセスして先ほどの画面が見れれば終了です。

 

今日は長くなったのでここまでにします。

開発環境ができた!

 

今回作成したファイルなどはこちらからどうぞ

https://github.com/dsrice/base_docker/tree/step1

はじめに

いろいろありましたが、

まず、Windows10 Proにアップグレードしました。

PCがあげる悲鳴がここ1年きになっているところではありますが、

Macに買い替えるにはいろいろとお金が・・・・

ということでアップグレードしました!!

 

サクッとHyper-Vを有効にして、

Docker Desctop on Windowsをインストールして

docker-compose upしたら何事もなくコンテナとの共有など成功!

なんでやねん!Vagrantに何が起こってるんだ・・・orz

 ちなみになぞのフォルダは管理者権限のコマンドプロンプトからでも消せません・・・・

 

mysqlとかのDBサーバを立てるときとかにつかうか

ホストOSに直接いれてもいいけど、

たまにDBの切り替えとかしたいときとかこれからたくさんあるだろうし

このままでOKですな!

 

手順

 *この方法をやるにはWindows10 Proが必要です。

 Windows10 Homeではできませんのご了承ください。

手順1 Hyper-Vを有効にする

手順2 Docker Desctop on Windowsをインストールする

手順3 Docker環境のための整備 

 

手順1 Hyper-Vを有効にする

Hyper-Vとは、Windows環境で仮想マシンを作成することができるものです。

Hyper-VWindows Proである必要があります。

Hyper-Vのみをインストールする方法はありませんので注意してください。

 

Windowsアイコンを右クリックして表示されるメニューの「アプリと機能」をクリックする

f:id:ds_ricekun:20200428231958p:plain

 

②表示されたウインドウの右側の「プログラムと機能」をクリックする

f:id:ds_ricekun:20200428232100p:plain

 

③左側にある「Windowsの機能の有効化または無効化」をクリックする

f:id:ds_ricekun:20200428232303p:plain



④表示されたポップアップからHyper-Vを探してチェックボックスにチェックをつける

f:id:ds_ricekun:20200428232436p:plain

 

⑤チェックとつけたら「OK」ボタンをクリックする。

 PCの再起動を促されます。有効にするのに必要ですので必ず実行してください。

 

手順2 Docker Desktop on Windowsをインストールする

①以下のURLにアクセスします。

 https://hub.docker.com/editions/community/docker-ce-desktop-windows/

 

②「Get Docker」をクリックします。

 クリックするとexeファイルのダウンロードが始まります。

 

f:id:ds_ricekun:20200428233424p:plain

③ダウンロードしたexeファイルを実行してください。

 表示された内容に従ってインストールをします。

 インストールを終えるとPCの再起動になります。

 再起動すると、Docker Desktop on Windowsが起動時に立ち上がるようになります。

 

 アイコンは上の図の左側にあるようなクジラのようなものになります。

 タスクバーの右側から展開すると起動状態を確認できます。

 

手順3 Docker環境のための整備

 djangoやangularまで話をするとまだまだ長くなってしまうので

ここではmysqlphpmyadminのみの環境でDockerが使えるようになったかを

確認するところまでにします。

近いうちにDjangoやAngularの話を書こうかと思います。

 

①作業ディレクトリを用意しましょう。

 場所はどこでもOKです。

 ただ、Docker関連はコマンドプロンプトからコマンドを実行する必要があります。

 パスを覚えさすなり、移動させやすいパスにするなど工夫が必要です。

 

②作業ディレクトリ内の構成を用意します。

 作業ディレクト

  ┣ーーcontents

  ┃  ┗ーーmysql

  ┃    ┣ーーDockerfile

  ┃    ┗ーーconf.d

       ┃              ┗ーーmy.conf

  ┗ーーdocker-compose.yml

 

フォルダ、ファイルの説明

 contensフォルダ

  Dockerの構成などの情報をまとめるためのフォルダです。

  今後の展開も踏まえてさらにmysql用にフォルダを切っています。

 

 Dockerfile

       拡張子がないですが今回作成するコンテナは最初に構成する情報をまとめたものです。mysqlのVersion upするときなどはこのファイルの変更が必要です。

 

 

FROM mysql:8.0
# 指定の場所にログを記録するディレクトリを作る
RUN mkdir /var/log/mysql
RUN chown mysql:mysql /var/log/mysql 
RUN chown mysql:mysql /var/lib/mysql
RUN chown mysql:mysql /usr/sbin/mysqld 
RUN touch /var/log/mysql/mysqld.log

EXPOSE 3306

 chownを書いていますが、なくても動くかもしれないです。

 ただ、権限不足などのエラーが出る際はあったほうがいいと思います。

 

 my.conf

       mysqlの設定をコンテナの外に出したものです。

  このようにしている理由は話が長くなるので今回は保留にします。

  今はこういうものだと思ってもらえれば幸いです。

  内容は、mysqlで設定に記載するmy.confと同じです。

  特別docker用のものはありません。

 

[mysql]
# 文字コードの設定
default-character-set = utf8mb4
[mysqld]
# 文字コード/照合順序の設定
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# デフォルト認証プラグインの設定
default-authentication-plugin = mysql_native_password
explicit-defaults-for-timestamp = 1  # テーブルにTimeStamp型のカラムをもつ場合、推奨
# 実行ログの設定
general-log = 1  # 実行したクエリの全ての履歴が記録される(defaultではOFFになっているらしい)
general-log-file=/var/log/mysql/mysqld.log # ログの出力先
# エラーログの設定
log-error = /var/log/mysql/mysql-error.log
# スロークエリログの設定
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 5.0
log_queries_not_using_indexes = 0

[client]
# 文字コードの設定
default-character-set = utf8mb4

 

 docker-compose.yml

      docker-composeコマンドで対応する内容になります。

   内容の説明は後日にします。(これだけでも1記事かけるので)

 

version'3'

services:
  db:
    build./contents/mysql
    container_namemysql
    restartalways
    environment:
      MYSQL_ROOT_PASSWORDroot
      MYSQL_DATABASEbowring
      MYSQL_USERbowring
      MYSQL_PASSWORDbowring
      TZ'Asia/Tokyo'
    command--innodb-use-native-aio=0
    volumes:
      - ./cache/db/ :/var/lib/mysql
      - ./contents/mysql/conf.d :/etc/mysql/conf.d/
      - ./log/mysql :/var/log/mysql
    ports:
      - 33306:3306
    
  phpMyAdmin
    container_namephpmyadmin
    imagephpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=mysql
      - PMA_USER=root
      - PMA_PASSWORD=root
    ports:
      - 8080:80

 

   注意点としては、portsのところです。

  ymlファイルですのでdbがmysqlのコンテナ情報、

 phpmyadminphpmyadminのコンテナ情報になります。

 portsの情報は ホストOS : ゲストOS のポート転送になります。

 私の環境はホストOS内にmysqlをインストールしているため

 ポートの3306はホストOSのmysqlがすでに使用しています。

 同じポートを指定しようとするとdockerのmysqlが立ち上がらなくなります。

 それを避けるためにポート転送を宣言しました。

 不要な方は3306にしてもらって構いません。

 大事なことはホストOS上で対象ポートを使用していないことです。

 

コマンドプロンプトからDockerを起動します。

  コマンドプロンプトに起動して、

  まず、用意した作業ディレクトリに移動します。

 

  次に

  「docker-compose build

  を実行します。

  このコマンドは初回時やDockerfileの内容を変更したときに使用します。

  このコマンドでコンテナイメージを作成しますのでDocker Hubに上げたい方は

  利用が増えると思います。

 

  「docker-compose up」を実行するとコンテナが起動します。

  初回起動時はmysqlの初期化などが走りますのですこし時間がかかります。

  コマンドプロンプトの動きが止まったらホストOSのブラウザから

   「http://localhost:8080

  にアクセスします。phpmyadminの画面が表示されたら成功です。

  

f:id:ds_ricekun:20200429005427p:plain

ちなみにphpmyadminでなくてもアクセス可能です。

ツールを使う際はポート指定に注意してください。

 

長くなりましたが、今日は以上です。

予定では、djangoやangular用のコンテナを追加して、

Dockerで用意したファイルのあれこれを話そうかと思います。

  

今回作成したファイルなどはこちらからどうぞ

https://github.com/dsrice/base_docker/tree/step1

 

Docker環境・・・・・

必要なもののインストールを終えて、

仮想環境の構築、ホストOSとゲストOS間の共有フォルダの作成

まではうまくいったのですが、・・・・

 

ここからDockerを今考えている構成でうごかすことができない・・・

しかも困ったことに謎のフォルダが生まれる・・・・

 

docker-compose up

をするとvolumesに指定しているフォルダが謎の子分を作り始めた。

しかも、コンテナ内はこの中身がない子分を見ている・・・・

 

一番の最悪なのはこの子分フォルダが削除できなくなる・・・

現時点では何しても消せない。

管理者権限できても削除できないって・・・・・

windows先生仕事してほしいっす・・・・

 

解決する見込みもないし、

作業環境が消せないフォルダが大量に埋めれるために汚れる・・・

 

一旦Docker環境はお見送りです。

(そもそもPCスペック的にも無理がある感じでもありました。)

 

仕事ではDocker環境で開発をしているのですが、

PCはMacなのです・・・・

こんなに違うの?ってらいwindowsで環境が作りづらい・・・・

 

ほかにもシンボリックリンク張ったら変な風に共有されたりと

やりたいことができなさそうでした。orz

 

素直にローカルで開発をすることにします。

PC限界説があるから今度はMacにしようかな~

と考える土日でした。

 

ちなみにやろうとしたことをまとめると

コンテナ構成

 front : anguler用のコンテナ

 api : django用のコンテナ

   開発はRESTFULL APIですすめるつもりだったからapiとつけました。

 db : DBはMySQLを利用予定でした。

   MySQLの起動は問題なくできるところまでいけたました~

 phpmyadmin : DBをあつかうためのツールの候補として用意しました。

        dbへのアクセスまではできるところまで行けました。

 

dbはMySQLでいくつもりだったので

最悪はDockerでDBだけ用意するという手段もありますね。

 

開発環境をdockerで用意する(Windows インストール編)

はじめに

大事な開発環境ですが、
私のPCはWindows10・・・・

pythonを使っていろいろするならAnacodaを入れて~
といったことが一般的なはず
nodeもPCにいれてもいいのですが・・・・

せっかくだからDockerで用意しよう!!

理由は、
1. Anacondaはあまり好きでない
2.Dockerを真面目に扱ってみたい!(今までは表面の薄い知識しかない)

なのでDockerで作る

環境の整理

windowsでdockerを扱うのによく見かけるのが
docker for windowsを使うこと

しかし、私のPCはHyper-Vに対応したものではないのです・・・orz
そんなわけで
Vagrant + VirtualBox
というVMを使った環境を用意することにする。

VittulBoxとは

とても有名な仮想化ソフトです。
ホストOS(自分のPCのOS)の中にゲストOSを入れることができるソフトになります。

そもそもDockerはLinux系のほうが相性がよいのでこれでLinux環境を用意します。
でも単純にVirtualBoxを扱うとOSのイメージ用意やホストOSとの共有の設定やら
と準備や設定が多い・・・・・ そこでVagrantの出番になります。

VirtualBox公式サイトはこちらから

Vagrantとは

Vagrantは仮想化ソフトをCUIで操作するソフトです。
ホストOSのコンソール上でVirtualBoxを扱えるようになる!というわけです。
こいつを使うことでゲストOSの指定からホストOSとの共有設定なども簡単になる

注意点 Vagrant単体では何もできません。あくまで仮想化ソフトをホストOSのCUIで操作できるようにするものです。
利用するにはVirtualBoxが必要ですので気を付けてください。

インストールをする

VirtualBoxをインストールします。

  1. VirtualBox公式サイトに移動します。
  2. 下図の赤枠から自分のPCのOSに合うものを選択します。
    f:id:ds_ricekun:20200424222448p:plain Windowsなら「Windows hosts」、Macなら「OS X hosts」をクリックしてください。
  3. クリックすると実行ファイルがダウンロードされますので、実行して指示に従ってインストールをしてください。
    今回の目的であるdockerの開発環境ではVirtualBoxから何かすることもないので終了です。

Vagrantをインストールします。

  1. VirtualBox公式サイトに移動します。
  2. 下図の赤枠から自分のPCのOSに合うものを選択します。
    f:id:ds_ricekun:20200424224252p:plain Windowsは32bitと64bit版で分かれているのでPC環境を確認してクリックしてください。
  3. クリックすると実行ファイルがダウンロードされますので、実行して指示に従ってインストールをしてください。

下準備完了になります。 思ったより長くなったので今日はここまで!!!