Docker Desktop for Windowsのファイル場所

WSL2を使用したWindows版のDockerでは、Overray2の保存場所がinspectした時に記載されている場所が異なります。

$ docker image inspect hello-world
[
    {
        "Id":..
    ...
        "GraphDriver": {
                "Data": {
                     "MergedDir": "/var/lib/docker/overlay2/9f8ec5a976d631b0096dd483c7b83f34137b3ffcde0ea177b5416086e4211423/merged",
                     "UpperDir": "/var/lib/docker/overlay2/9f8ec5a976d631b0096dd483c7b83f34137b3ffcde0ea177b5416086e4211423/diff",
                     "WorkDir": "/var/lib/docker/overlay2/9f8ec5a976d631b0096dd483c7b83f34137b3ffcde0ea177b5416086e4211423/work"
                 },
                 "Name": "overlay2"
          },
     ....

というように記述されていますが、WSL2で/var/lib/dockerディレクトリは存在していません。
DockerはWSL2同様にLinuxカーネルを使用するため、実際にはWindows上に仮想マシンを起動(Docker Desktop)しており、上記パスはその仮想マシン内のパスを表しています。

どこから見れるのか、というとWindowsでは下記の場所に存在しています。
\\wsl$\docker-desktop-data\version-pack-data\community\docker\overlay2\9f8ec5a976d631b0096dd483c7b83f34137b3ffcde0ea177b5416086e4211423\diff


試しにテストで新しくボリュームを作成してみます。
\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes
にボリュームが格納されてますが、今はボリュームが1つも作成されていない状態なので、最初から存在しているmetadata.dbしかありません。

$ docker volume ls
DRIVER              VOLUME NAME

ボリュームを新しく作成します。

$ docker volume create vol_test
vol_test
$ docker volume ls
DRIVER              VOLUME NAME
local               vol_test
$ docker volume inspect vol_test
[
    {
        "CreatedAt": "2020-10-19T08:22:13Z",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/vol_test/_data",
        "Name": "vol_test",
        "Options": {},
        "Scope": "local"
    }
]

Mountpointは、"/var/lib/docker/volumes/vol_test/_data"と記載されていますが、WSL上では、
\\wsl$\docker-desktop-data\version-pack-data\community\docker\volumes\vol_test\_data
に新しく作成されています。
(しかし、Ubuntuからこのディレクトリを参照する方法がわかりません...誰か教えてください)

ホストOSがLinuxの場合は、ホストOSのファイルシステムを利用しているとのことです。
WSL2はHyper V上にLinuxカーネルを再現しているため

Overray2に関する記事は下記で詳しく書かれてますので参考に。
qiita.com
tech-lab.sios.jp

Ubuntu 初期設定(ls、vimの色とか)

Ubuntu 18.0.4をインストールした直後の設定をメモしておきます。
特にlsとvimの色が見にくいのでその辺変えていきます。

lsの色変更

lsの色はLS_COLORSという環境変数に設定しますが、直接編集するのは大変なため、dircolorsコマンドを使います。

1.設定ファイルをgitからclone
$ git clone https://github.com/seebi/dircolors-solarized.git .dircolors-solarized

.dircolors-solarizedディレクトリには以下の4つの設定ファイルがあり、この中から色を選びます。
・dircolors.256dark
・dircolors.ansi-universal
・dircolors.ansi-dark
・dircolors.ansi-light
今回はdircolors.256darkにします。

2.dircolorsコマンドで設定ファイルを読み込む
$ eval $(dircolors ~/.dircolors-solarized/dircolors.256dark)

これだけで変更完了。
設定前
f:id:zamdin:20201014211828p:plain
設定後
f:id:zamdin:20201014211843p:plain
特にディレクトリの紺色が水色に変わり見やすくなっています。

3.bashrcに記述

今のままでは再起動すると設定が元に戻るため、eval文を.bashrcに書いておく。

vimの色変更

vimの色を変更するには:colorschemeコマンドで確認、変更できる。

1.vimで適当なファイルを開き、:colorscheme[space][tab]と入力

tabを押すたびに、blue、dark blue....などと入力値が変わっていく。Eneterを押せば即時にvimの色が変わる。
これで好きな色セットを確認していく。
しかし、これは一時的な設定のため、.vimrcファイルに設定を保存する必要がある。

2..vimrcファイルを作成し、colorschemeを記述

.vimrcファイルがない場合は$HOMEに.vimrcファイルを作成する。

$ vim .vimrc

作成と同時に編集モードになるので、iを押して、

colorscheme [好きな色]

と一行記述して保存(:wq)すれば、今後は設定した色が適用される。
個人的にはronがおすすめ。

プロンプトの変更

プロンプトは$PS1という環境変数に格納されている。

$ echo $PS1
\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$

中間の辺りにある、\u@\hの部分が実際に表示される部分

\u ユーザー名
\h ホスト名
\W 今いるディレクトリ名
\$ 一般ユーザーの時「$」、rootの時「#」

また、色は\u@\hの手前の、[\033[01;32m\]の部分

0;30m Black 1;30 Dark Gray
0;31m Red 1;31m Light Red
0;32m Green 1;32m Light Green
0;33m Yellow 1;33m Light Yellow
0;34m Blue 1:34m Litght Blue
0;35m Purple 1;35m Light Perple
0;36m Cyan 1;36m Light Cyan
0;37m Light Gray 1;37m White

実際の変更は.bashrcにPS1=で始まる同文が記述されているため、そこを編集する。

if [ "$color_prompt" = yes ]; then
    PS1='${debian_chroot:+($debian_chroot)}\[\033[0;36m\]\u\[\e[0:36m\]:\[\033[0;36m\]\w\[\033[0;37m\]\$ '

編集後は、source .bashrcをして変更を反映させる。

ゼロからDjango環境構築(Windows10 WSL、Docker)

Windows 10でDockerコンテナ内にDjango環境を構築します。
経緯としては、WSLのAnaconda環境でDjangoをインストールしてマイグレーションファイルを作ろうとしたところ、以下のようなエラーが出たためです。

$ python manage.py makemigrations
ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?

詳しくは分かりませんが、AnacondaとDjangoは相性が悪いみたいです...
なので、vnen(Docker使用)環境で作り直そうと思います。
また、Dockerコンテナに構築しておくことで、ホスト環境を汚すことがなくなり、違う環境(Mac OSとか)にも全く同じ環境を展開することが出来るようになります。
さらに今回インストールするVS Codeエディタのリモート拡張機能を用いれば、開発対象のリソースがコンテナ内にあったとしてもローカルで開発するかのように作業が行えるようになります。

構築前環境

Windows 10 Pro Version1903
WSL Ubuntu 16.0.4

1.Docker Desktop for Windowsのダウンロードとインストール

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

登録していない場合は、Sign Up → Get Docker
 

2.Ubuntu 18.0.4のインストール

インストールする前にWSL2をデフォルトにするよう設定を変えます。
WS2の要件はx64 システムの場合、バージョン 1903 以降、ビルド 18362 以上です。


WSL2でのUbuntu環境を作るために、以下のコマンドを実行します。

wsl --set-default-version 2

これでWSL2がデフォルトに設定されたので、Microsoft Storeから今回hUbuntu18.0.4 LTSをインストールします。
その後、再度以下のコードを実行してWSLのバージョンを確認します。

PS C:\Users\alice> wsl --list --verbose
  NAME                   STATE           VERSION
* Ubuntu-16.04           Stopped         1
  Ubuntu-18.04           Running         2
  docker-desktop-data    Running         2
  docker-desktop         Running         2

ちなみに、WSLとWSL2ではファイルシステムが違うため、データへのアクセス方法が異なります。

WSL ボリュームファイルシステムVolFsNTFS上)
C:\Users\{User名}\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu16.04onWindows_79rhkp1fndgsc\LocalState\rootfs\
WSL2 Ext4ファイルシステム(VHDX内)
C:\Users\{User名}\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_79rhkp1fndgsc\LocalState\ext4.vhdx
\\wsl$\Ubuntu-18.04\

WSL2では9Pネットワークプロトコルを利用しているため、Windowsからはネットワーク接続で参照できます。


3.Docker Desktopの設定

1.でインストールしたDocker Desktopを開き、Settings > Resources > WSL INTEGRATION > Ubuntu-18.04を有効化し「Apply & Restart」で適用します。
f:id:zamdin:20201017150605p:plain
Ubuntu 18.0.4を開き、docker --versionでWSL2でDockerが認識されていることを確認します。

$ docker --version
Docker version 19.03.13, build 4484c46d9d

テストとしてhello-worldイメージを実行し、コンテナ一覧を出力してみます。

$ docker image ls --all
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello-world         latest              bf756fb1ae65        9 months ago        13.3kB
$ docker container run hello-world
Hello from Docker!
$ docker container ls --all
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS                          PORTS               NAMES
3d13e334b944        hello-world         "/hello"            About a minute ago   Exited (0) About a minute ago                       trusting_mendel

hello-worldコンテナが起動されていることが確認できましたので、コンテナを削除しておきます。
コンテナを削除するときは、docker container rmの後にコンテナIDを指定します。前頭検索で指定可能です。

$ docker container rm 3d

また、dockerと打つことでDockerで使用できるコマンド一覧が表示されます。
コンテナの仕組みについては以下の記事で詳しく書かれています。
qiita.com


4.Dockerファイルの場所を変更

デフォルトではDocker HubからpullしたイメージファイルはCドライブにダウンロードされていき圧迫されていくため、下記を参考にDockerイメージファイルの場所をDドライブに変更します。
qiita.com


5.Dockerイメージの作成

コンテナ作成の元となるイメージファイルを作成します。
まず、Docker Hubからイメージをダウンロード(pull)します。

コマンド docker pull {イメージ名}:{タグ名}

イメージ名とタグ名は下記Docker Hubページから探します。
https://hub.docker.com/
今回は、ubuntu:l20.10と指定し、ubuntuのバージョン20.10のイメージをダウンロードします。

$ docker pull ubuntu:20.10
$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              20.10               da5958a2de8e        36 hours ago        79.5MB


Dcokerfileは以下のGithubページのコードを流用させて頂きます。
https://github.com/akiyoko/django-book-mysite-sample/blob/master/Dockerfile
mysiteというディレクトリを作成し、その直下に下記コードをDockerfileという名前で保存します。

FROM ubuntu:20.10

ENV PYTHONUNBUFFERED 1
ENV PYTHONIOENCODING utf-8

ENV HOME /root
ENV DEPLOY_DIR ${HOME}/mysite

RUN apt update \
&& apt install -y sudo \
&& apt -y upgrade

# Set locale
# https://stackoverflow.com/a/28406007
RUN apt install -y locales
RUN sed -i -e "s/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/" /etc/locale.gen \
    && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

# Install Python 3.8
RUN apt install -y wget \
    build-essential \
    zlib1g-dev \
    # https://stackoverflow.com/a/43923402
    libssl-dev \
    # https://stackoverflow.com/a/29862854
    libsqlite3-dev

WORKDIR ${HOME}

RUN wget https://www.python.org/ftp/python/3.8.0/Python-3.8.0.tgz \
    && tar zxf Python-3.8.0.tgz \
    && cd Python-3.8.0 \
    && ./configure --enable-optimizations \
    && make altinstall

# Set alias
RUN update-alternatives --install /usr/local/bin/python3 python /usr/local/bin/python3.8 1
RUN update-alternatives --install /usr/local/bin/pip3 pip3 /usr/local/bin/pip3.8 1
RUN pip3 install -U pip

# Install other requisites
RUN apt install -y vim

RUN mkdir -p ${DEPLOY_DIR}
WORKDIR ${DEPLOY_DIR}

# Install packages for project
ADD requirements.txt .
RUN pip3 install -r requirements.txt

CMD ["/bin/bash"]

requirements.txt には、Djangoだけインストールするように書いてます。

Django==3.1.2 

その後、dockerイメージをビルドします。

$ docker image build -t mysite:1.0 .

tオプションでイメージ名:タグ名を指定します。
. はDockerfileの保存場所(カレントディレクトリ)を指定しています。

$ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mysite              1.0                 39782a5aeaca        42 seconds ago      991MB
ubuntu              20.10               da5958a2de8e        4 days ago          79.5MB

6. コンテナ作成

次のコマンドでDockerイメージからコンテナを作成します。

$ docker container run -it -p 8000:8000 -v /home/py/mysite:/root/mysite --name mysite mysite:1.0
-t コンテナの中に疑似ターミナルを割り当てる
-i 標準入力(STDIN)を取得
-v ボリュームを割り当てる(マウント)ホスト:コンテナ
--name コンテナ名
mysite:1.0 イメージ名:タグ名

今回、Dockerfileの中でCMD ["/bin/bash"]と設定しているため、docker runでの記述は不要です。
itと/bin/bashはセットで使用します。
これでホストディレクリがコンテナのディレクトリにマウントされた状態でコンテナが起動します。

root@cd0c0a5f847d:~/mysite# ls
Dockerfile  requirements.txt  test.php  venv
root@cd0c0a5f847d:~/mysite# pwd
/root/mysite

通常は、マウントしたホストディレクトリをプロジェクトフォルダとして作業していきます。
コンテナのターミナルから抜けたい場合はexitを打ちます。


Dockerの操作

存在しているDocker一覧 $ docker container ls -a
起動しているDocker一覧 $ docker container ls
起動しているDockerの停止 $ docker container stop {コンテナ名}
起動しているDockerの削除 $ docker container rm {コンテナ名}

Python3のインストール

コンテナ内にPythonをインストールすればいいので、必ずホストOSにPythonをインストールする必要もないかもしれませんが、
Pythonのインストール方法もメモします。
執筆時点でPython 3.8がリリースされていたので、3.8をインストールします。

$ sudo apt update
$ sudo apt install -y python3.8
$ python3 -V
Python 3.6.9

3.8をインストールしたのに、3.6.9となってます。
Ubuntu18.0.4のインストールした初期からPython3.6.9もインストールされてたみたいです。

$ ls /usr/bin/ | grep python
python3
python3-jsondiff
python3-jsonpatch
python3-jsonpointer
python3-jsonschema
python3.6
python3.6m
python3.8
python3m

しっかり3.8もインストールされているみたいで、切り替える必要があります。

$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 1
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2
$ sudo update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).

  Selection    Path                Priority   Status
------------------------------------------------------------
* 0            /usr/bin/python3.8   2         auto mode
  1            /usr/bin/python3.6   1         manual mode
  2            /usr/bin/python3.8   2         manual mode

Press <enter> to keep the current choice[*], or type selection number: 2
$ python -V
Python 3.8.0

update-alternatives --install [symbolic link path] python [real path] number
という風で、pythonのバージョンを登録することで切り替えられるようになります。
pythonと打つと/usr/bin/pythonが呼び出され、そこは/etc/alternatives/pythonを参照します。さらにその参照先を今回は/usr/bin/python3.8にした感じ)
ちなみに、python3と打つと3.6.9が参照されています。

$ python3 -V
Python 3.6.9
$ which python3
/usr/bin/python3

python3はpythonとは元々2系と3系を分けるために存在しているようですが、2系は自分は使わないので別にこれで良いと思います。
パッケージ管理ツールpipのインストールとアップグレードも行います。

$ apt install python3-pip
$ python -m pip install --upgrade pip
$ pip --version
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
pip 20.2.3 from /home/py/.local/lib/python3.8/site-packages/pip (python 3.8)

pipはそのままpipと打つと上記のようにWARNINGが出ます。
この書き方は古いようで、python -m pipという記法が正しいとのことです。

$  python -m pip -V
pip 20.2.3 from /home/py/.local/lib/python3.8/site-packages/pip (python 3.8)
$ python3 -m pip -V
pip 9.0.1 from /usr/lib/python3/dist-packages (python 3.6)

これもpython3と打つと、3.6環境のpip(インストールしただけでアップグレードしていないpip)を参照します。

.bash_aliasesファイルにalias pip='python -m pip'と記述しておけば、pipだけで済むので楽です。


venv仮想環境構築

コンテナ自体が仮想環境のように環境構築できるため、別途venv仮想環境も要らないとは思いますが、
一応venvの使い方もメモ。

venvはPythonの仮想環境を簡単に構築する機能で、主にpip(パッケージ管理ツール)でインストールするパッケージをプロジェクトごとに分けたい時に利用します。
Python3.3~標準でインストールされており、基本的に1プロジェクト1venv仮想環境を用意します。
また、Python3.5~は仮想環境を作成する際にはvirtualenvやpyenvではなくvenvが推奨されています。

今回はDjangoプロジェクトとして、mysiteディレクトリを作成し、そこにvenv仮想環境を構築します。

$ mkdir mysite
$ cd mysite
$python3 -m venv venv

これでvenvという名前の仮想環境が作られます。
仮想環境のアクティベート

$ source venv/bin/activate
(venv) $ python -V
Python 3.8.0

venv仮想環境内のPythonバージョンはローカルのPythonバージョンと同じになります。

(venv) $ pip  --version
pip 9.0.1 from /home/{User名}/mysite/venv/lib/python3.8/site-packages (python 3.8)

pipのバージョンもvenv仮想環境を参照しているため9.0.1のままですので、アップグレードします。

(venv) $ pip install --upgrade pip
(venv) $ pip  --version
pip 20.2.3 from /home/{User名}/mysite/venv/lib/python3.8/site-packages/pip (python 3.8)

【PostgreSQL】ロールの削除

PostgreSQLでロールを削除する方法について

 

testロールを削除したいが、testロールには同名のtestデータベースを所有しているため、削除しようとすると以下のようにエラーとなる。

postgres=# DROP ROLE test;
ERROR: role "test" cannot be dropped because some objects depend on it
DETAIL: owner of database test

 

PostSQLでは、削除したいロールがスキーマ、テーブル、データベースの所有者の場合は、それらを削除するか所有権を他のロールに変更しておく必要がある。

postgres=# DROP DATABASE test;
DROP DATABASE
postgres=# DROP ROLE test;
DROP ROLE

 

もし複数の所有権を持っており、それらを一度に削除したい場合はdrop ownedを使用します。

DROP OWNED BY role名

PostgreSQL ログイン、ロールの追加、DB作成

前回インストールした直後の続きから

1.PostgresSQLにログイン

今、"py"というユーザーでUbuntuにログインしており、そのままpsqlと打つと以下のエラーが出る。

$ psql
psql: error: could not connect to server: FATAL: role "py" does not exist

"py"というロールは存在しないという。。

 

Postgresは、インストールと同時にpostgresというロール(ユーザー)が自動作成されます。

※ロールはDBにアクセス権などを付与する役割を持ち、postgresはスーパーユーザーといい全ての権限が与えられている。

なので、最初にpostgresユーザーに切り替える。

$ sudo su - postgres

 

これでPostgreSQLを動かせるようになった。

$ psql
psql (13.0 (Ubuntu 13.0-1.pgdg16.04+1))
Type "help" for help.

postgres=#

 

2.ロールの追加

今存在しているロール一覧は、\duコマンドで分かる。

f:id:zamdin:20201012223548p:plain

testロールの作成

postgres=# CREATE ROLE test LOGIN CREATEDB PASSWORD 'test';
CREATE ROLE

 

f:id:zamdin:20201012223630p:plain

[属性の説明]

https://www.postgresql.jp/document/9.3/html/role-attributes.html

 

3.DBの作成

postgres=# CREATE DATABASE test OWNER test;

\lコマンドでデータベース一覧が分かる。

f:id:zamdin:20201012224352p:plain

PostgreSQLの終了は、\q

 

4.新しく作ったロールにログイン

$ psql --username=test --password --dbname=test
Password: パスワードを入力
psql: error: could not connect to server: FATAL: Peer authentication failed for user "test"

エラーが出ました。クライアント認証なる設定が必要とのことで、普段ログインしているユーザー名と同じものでないと上記エラーが出ます。

 

[pg_hba.confの編集]

$ sudo vim /etc/postgresql/13/main/pg_hba.conf

# TYPE DATABASE USER ADDRESS METHOD

# "local" is for Unix domain socket connections only
local all all peer

peer → trust に変更する

 

[PostgreSQLの再起動]

$ sudo /etc/init.d/postgresql restart
* Restarting PostgreSQL 13 database server

 

これで新しいロールでログイン出来るようになった。

$ psql --username=test --password --dbname=test
Password:
psql (13.0 (Ubuntu 13.0-1.pgdg16.04+1))
Type "help" for help.

test=>

PostgreSQL 13のインストール(Ubuntu16.0.4)

UbuntuPostgreSQL 13をインストールする方法のメモ

 

実施環境

Windows 10

Ubuntu 16.0.4 (WSL)

 

1.Ubuntuのアップデート

$ sudo apt update

$ sudo apt -y upgrade

 

2.認証キーとリポジトリの追加

$ wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

$ echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |sudo tee /etc/apt/sources.list.d/pgdg.list

サードパーティのアドオンが含まれているリポジトリも追加しておく。

$ echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg-testing main 13" |sudo tee /etc/apt/sources.list.d/pgdg-testing.list

 

3.PoostgreSQL 13のインストール

$ sudo apt update

$ sudo apt install postgresql-13 postgresql-client-13

 

4.サービス起動

$ sudo service postgresql start

→ Error

LOG: could not bind IPv4 address "127.0.0.1": Address already in use

HINT: Is another postmaster already running on port 5432?

 

ポート5432が既に使われているとのこと。

f:id:zamdin:20201012214921p:plain

Ubuntuとは別にWindowsコマンドプロンプトでも使っていました。。

終了して再度実行したら無事起動しました。

$ sudo service postgresql start
* Starting PostgreSQL 13 database server

サービスの稼働状況確認

 $ service --status-all | grep post

[ + ] postgresql

サービスの終了

$ sudo service postgresql stop
* Stopping PostgreSQL 13 database server

/* -----codeの行番号----- */