Githubでローカルのリポジトリをリモートに作成する方法

背景

ローカルでコツコツ実装していたリポジトリを周りのメンバーに共有するためにGithubにpushしたりするときもあると思います。

たまにしか行わない作業で忘れがちなのでメモしておきます。

リモートにリポジトリを作成する

Githubにログインしてリポジトリを作成します。

わたしはだいたい~/github/リポジトリ名というディレクトリを作成しているので、このディレクトリに合わせたリポジトリ名にします。

リモートにリポジトリをpushする

リポジトリ作成後に次のアクションの例が表示されるので、それを参考にします。

ローカルになにもない場合

作成したリポジトリをクローンしてからcommit, pushします。
SSH or HTTPSでクローンします

コマンドラインで新しいリポジトリを作成する場合

クローンするのではなく、ローカルでディレクトリを作成してリポジトリとします。

1
2
3
4
5
6
7
echo "# リポジトリ名" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/オーガナイゼーション名/リポジトリ名.git
git push -u origin main

既存のリポジトリをコマンドラインでpushする場合

今回のケースはこちらにあたります。

1
2
3
git remote add origin https://github.com/オーガナイゼーション名/リポジトリ名.git
git branch -M main
git push -u origin main

-Mオプションってなんでしたっけと思ったので調べてみました。

1
2
3
4
With a -m or -M option, <oldbranch> will be renamed to <newbranch>.
If <oldbranch> had a corresponding reflog, it is renamed to match <newbranch>,
and a reflog entry is created to remember the branch renaming.
If <newbranch> exists, -M must be used to force the rename to happen.

(見やすいよう改行を入れています)

既存のブランチ名をmainに変えてくれってことみたいですね。

いつからこのようになったのでしょうか?調べてみると以下の記事が出てきました。

GitHub、これから作成するリポジトリのデフォルトブランチ名が「main」に。「master」から「main」へ変更

1年くらい前からそうなってたんですね…知りませんでした…

ということで、今後はmainにしていこうと思います。

別のリポジトリからインポートする

リポジトリのURLを指定することで既存のリポジトリをインポートできるようです。

実際にやってみる

では先程作成したGithubのリポジトリをリモートに設定します。

まず現在の設定状況を確認します

1
$ git remote -v

なにも表示されないので設定はされていません。

ではリモートを追加します。

1
$ git remote add origin https://github.com/オーガナイゼーション名/リポジトリ名.git

追加できているか確認します。

1
2
3
$ git remote -v
origin https://github.com/オーガナイゼーション名/リポジトリ名.git (fetch)
origin https://github.com/オーガナイゼーション名/リポジトリ名.git (push)

設定できました。

ではブランチ名をmainに変更します。

1
2
$ git branch
* master

今はmasterのみです。

1
2
3
$ git branch -M main
$ git branch
* main

変更できました。

最後にpushします。

1
2
3
$ git push -u origin main
remote: Repository not found.
fatal: repository 'https://github.com/オーガナイゼーション名/リポジトリ名.git/' not found

うーん、プライベートリポジトリだから認証がうまくいってないようですね。remoteのURLにユーザー名を追加してみます。

リモートを追加するには一度削除してから追加します。

1
2
$ git remote rm origin
$ git remote add origin https://ユーザー名@github.com/オーガナイゼーション名/リポジトリ名.git

もう一度pushしてみます。

1
2
3
4
5
6
7
8
9
10
11
$ git push -u origin main
Enumerating objects: 45, done.
Counting objects: 100% (45/45), done.
Delta compression using up to 8 threads
Compressing objects: 100% (39/39), done.
Writing objects: 100% (45/45), 7.56 KiB | 1.51 MiB/s, done.
Total 45 (delta 17), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (17/17), done.
To https://github.com/オーガナイゼーション名/リポジトリ名.git
* [new branch] main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

無事pushできました。

まとめ

最初は自分だけで開発している場合ものちにGithubリポジトリにpushしてチーム開発していくことが多くあると思います。

いつでもpushできるよう準備しておくのが良さそうですね。

参考図書

複数のgitアカウントの利用方法

背景

Macのリプレースを行って(最近はこればっかり)、git関連の設定もふっとんでいます。

Macでは、会社用・プライベート用などいろんなgithubのアカウントを利用しています。複数のgitアカウントを設定する時のわかりやすい方法を調べました。

普段は1度設定したらあまり設定することのないGitの設定をまとめたいと思います。

事前準備 git: ‘secrets’ is not a git command. See ‘git –help’.

Macで一番最初にgit commitしようとしたら、エラーが発生しました

1
git: 'secrets' is not a git command. See 'git --help'.

ググってみると、git-secretsをインストールする必要があるようでした。

1
$ brew install git-secrets

こちらでエラーはなくなります。

設定の方針

設定の方針としてはメインで利用するアカウントをglobalに設定し、それをオーバーライドしたいリポジトリではlocalでアカウントを設定します。

そうすることで、よく使うアカウントがデフォルトの設定になり、手間が省けます。

よく利用するアカウントの設定

会社のPCだと、会社のGithubのアカウントを利用することが多いです。なので、会社のGithubアカウントをglobalに設定します。

まず現在の設定を確認してみます。

1
2
$ git config --global --list
fatal: unable to read config file '/Users/user/.gitconfig': No such file or directory

そもそもファイルがありませんでした…コマンドでuser.nameuser.emailを設定してみます。

1
2
$ git config --global user.name "会社のアカウント名"
$ git config --global user.email "会社のメールアドレス"

反映されていることを確認します

1
2
3
4
$ git config --list
credential.helper=osxkeychain
user.name=会社のアカウント名
user.email=会社のメールアドレス

プライベートのアカウントの設定

プライベートなGithubアカウントを設定したいリポジトリのディレクトリに移動します。

そこでgit config --local --listを実行します。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git config --local --list
user.name=会社のアカウント名
user.email=会社のメールアドレス
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/プライベート/xxxxxxx.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master

globalで設定した会社のメールアドレスが設定されています。ここで、git config --localを利用して、アカウント名とメールアドレスを設定してみます。

1
2
$ git config --local user.name "プライベートのアカウント名"
$ git config --local user.email "プライベートのメールアドレス"

反映されていることを確認します

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git config --local --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/プライベートのアカウント名/xxxxxxx.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
user.email=プライベートのメールアドレス
user.name=プライベートのアカウント名

正しく反映されていました。

設定は~/.git/configに保存されています。確認してみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat .git/config 
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = https://github.com/プライベートのアカウント名/xxxxxxx.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[user]
email = プライベートのメールアドレス
name = プライベートのアカウント名

しっかり保存されていました。

git commitして動作確認

実際にgit commitして、ログメッセージがどうなるかを確認します。

1
2
3
4
5
6
7
8
9
$ git commit -m "git commitのテストのためにコミット"
[mastet xxxx] git commitのテストのためにコミット
1 file changed, .....
$ git log
commit xxxxxxxxxxxx (HEAD -> master)
Author: プライベートのアカウント名 <プライベートのメールアドレス>
Date: Fri Sep 10 23:23:58 2021 +0900

git commitのテストのためにコミット

アカウント名、メールアドレスともに正しく認識されています。

これでgitの複数アカウントでの設定が完了しました。

おまけ

gitの設定がされていない場合、アカウント名はMacのログイン名、メールアドレスはMacのアカウント@ホスト名となります。

まとめ

Gitの設定はスムーズに開発を行うために必須です。アカウントを正しく設定できていないと、Githubでコミットログでも正しいアカウントがヒョ次されていることが好ましいです(誰による変更かわからなくなってしまうため)

今回基本的な設定を行いましたが、これからもgitの設定を育てていきたいと思います。

参考図書

pyenvを使ってVSCodeで利用するpythonのバージョンを指定する

背景

Macのリプレースを行ったときにVSCodeの設定の引き継ぎを行わなかったので、最初から設定することになってしまいました。

Pythonのインストールとバージョンの切り替えにはpyenvを利用していたので、引き続き使っていこうと思っていましたが、VSCodeのpythonプラグインをインストールした後のpython実行ファイルの指定で少し詰まってしまったことを記載します。

pythonプラグインのインストール

VSCodeで.pyのファイルを開くと、VSCodeからpythonプラグインのインストールを勧められるので、そのままインストールします。

インタプリタの設定

プラグインのインストールが終わると、インタプリタの設定画面が表示されます。Pythonをインストールする、インタプリタを選ぶなどの選択肢がありますが、pyenvでPythonをインストールしていなかったのでまずはpyenvでPythonをインストールします。

pyenvでPythonをインストールする

以前から利用していた3.9.6をインストールします(現時点での最新版は3.9.7)

1
2
3
4
5
6
7
8
9
$ pyenv install 3.9.6
python-build: use openssl@1.1 from homebrew
python-build: use readline from homebrew
Downloading Python-3.9.6.tar.xz...
-> https://www.python.org/ftp/python/3.9.6/Python-3.9.6.tar.xz
Installing Python-3.9.6...
python-build: use readline from homebrew
python-build: use zlib from xcode sdk
Installed Python-3.9.6 to /Users/user/.anyenv/envs/pyenv/versions/3.9.6

インストールできました。パスを確認しておきます。

1
2
$ which python
/Users/user/.anyenv/envs/pyenv/shims/python

次にVSCodeでインタプリタの指定を行います。

インタプリタの指定

VSCodeのインタプリタの指定で、インタプリタを選ぶを選択し、先ほど確認したパスのファイルを指定します。

ステータスバー(画面一番下の水色のバー)にPythonのバージョンが表示されるのですが、なぜかPython2.7となっています…

もう一度バージョンとパスを確認します。

1
2
3
4
$ which python    
/Users/user/.anyenv/envs/pyenv/shims/python
$ python --version
Python 3.9.6

ん〜原因がわかりません…

ステータスバーに表示されているPythonのバージョンをクリックすると、インタプリタの選択ができます。

インタープリターの選択と書かれている右に再読み込みボタンがあるので、それをクリックしてみると、先ほどインストールした3.9.6のパスが表示されました。

表示されたバージョンをクリックすると無事3.9.6が選択されたようです。ステータスバーのバージョンも更新されていました。

まとめ

VSCodeは上手に設定しないとその便利さを引き出すことができません。設定したりするのは少し面倒な気がしますが、最初だけなので、しっかりと設定して開発効率を上げていけるようになりたいです。

参考図書

VSCodeのターミナルでctrl-pが効かない時の対処法

背景

前回から引き続きVSCodeでおかしな挙動になりました。

VSCodeのターミナルはVSCode内でシェルを使えるので重宝しています。ここでコマンドを実行したりするので、ctrl-p、ctrl-n, ctrl-rはよく利用します。

新しいMacに変えて、VSCodeのターミナルでctrl-pを入力すると、

1
^P

とだけ表示されるようになってしまいました。これはめちゃくちゃ不便…シェルをちゃんと利用したいです。ということで対応方法を記しておきます。

zshの問題かどうかの確認

まずはシェルの問題なのかどうかを確認するため、いつも使っているterminalで確認してみようと思います。

普段使っているterminalソフトはiterm2です。では入力してみましょう。

1
$ ^P^P^P

ダメですね…この問題はVSCodeの問題ではなく、シェルが変わったことによるもののようです。

ググってみると、同じような目に合っている人が何名かいらっしゃるようです。対応方法としては、.zshrc

1
bindkey -e

を実行してシェルを再起動するといけるようです。やってみましょう。

1
2
3
4
5
6
7
8
$ ^P^P^P
# この時点ではまだダメ
$ vi ~/.zshrc
# bindkey -eを追記
$ exec $SHELL -l
$
$ exec $SHELL -l
# ctrl-pで以前実行したコマンドが表示できた

VSCodeのターミナルでもシェルを再起動することでctrl-pを入力すると前のコマンドが表示されるようになります。

まとめ

zshに不慣れで、今までbashでいいって思っていたのですが、これを機にzshについてしっかりと理解していこうと思いました。

VSCodeでキーボードの長押しができなくなったときの対処方法

背景

最近会社で利用しているMacのリース期限が近づいてきたので、新しいMacにリプレースすることにしました。

VSCodeの環境はそのまま移行せずに1から綺麗な状態で作成しようと思い、初期設定を行いました。

いざ開発するとなって、Vimプラグインを入れ忘れていることに気づき、インストールしました(vscodevim)。

いざ実装しようと思って、jklhキーを使ってカーソルを移動させていたところ、長押ししてもカーソルが動かないことに気づきました。

これはとても不便です…なんとかしないといけません…その時の対応方法を記載します。

Macの設定を疑う

Macをリプレースしたこともあって、最初はMacの設定だと思っていました。

Macのキーボードの設定はシステム環境設定キーボードからキーボードタブで、リピート入力認識までの時間を一番短くしてみました。

結果、なにも変わらず、原因はここではないことがわかりました。

ググってみる

全くあてがなかったので、とりあえずググってみました。

VSCode 連打 offという謎のワードで検索したところ、以下のページが見つかりました。

VSCodeにMacVimから乗り換え!基本設定して使ったら快適だ…

このページ内で連打で検索したところ、原因がvimプラグインにあることがわかりました。プラグインのページにも記載されています。

To enable key-repeating execute the following in your Terminal and restart VS Code:

1
2
3
4
$ defaults write com.microsoft.VSCode ApplePressAndHoldEnabled -bool false         # For VS Code
$ defaults write com.microsoft.VSCodeInsiders ApplePressAndHoldEnabled -bool false # For VS Code Insider
$ defaults write com.visualstudio.code.oss ApplePressAndHoldEnabled -bool false # For VS Codium
$ defaults delete -g ApplePressAndHoldEnabled # If necessary, reset global default

今回は上の2行のみ実行しました。

再起動、動作確認

コマンド実行すると、とくにメッセージは表示されないのですが、無事実行できたようです。

最後にVSCodeを再起動します(再起動しないと反映されません)。

起動後、長押しでカーソル移動できるようになりました。

まとめ

VSCodeで初めてハマりました。いろんなプラグインがあるからか、たまにこういうことが起こるかもしれません。VSCodeでなにか起こったらまず直近にインストールしたプラグインを調べるようにしようと思います。

AWS Batchを試してみる

背景

前回Djangoのカスタムコマンドを試しに追加してみました。

今回はこのカスタムコマンドをAWS Batchで実行してみたいと思います。

AWS Batchとは?

AWS Batchは今回初めて利用するので、何なのかを知っておく必要があります。

AWSサービスの学び方としては、AWS Black Belt Online Seminarを受けるとよいとAWS認定資格試験の本に書いてあったので、見てみることにしました。

その動画はこちらになります。
[AWS Black Belt Online Seminar] AWS Batch 資料及び QA 公開

資料はこちらです。

わかったこととしては、以下のようになります。

  • 通常のバッチを実行するためではなく、ハイパフォーマンスなりソースが必要な場合に用いるサービスである。(資料P.9)
    • しかし通常のバッチ処理をしてはいけないというわけではない
  • S3 Batchというサービスもある
  • 最終的なデータのIN/OUTにはS3を用いることが多い
  • ジョブ完了ステータスからSNSを利用してSlack通知をすることができる
  • ジョブの投入方法(資料P.48)
    • ユーザーが手動で投入(マネジメントコンソール/CLI)
    • S3へのファイルアップロードをトリガーにLambdaからアップロードされたファイルを処理するジョブを投入
    • Cloud Watch Eventsにより決められた時刻にジョブを投入
  • スポットインスタンスの活用を検討すべき
  • 複雑なワークフローを実現するためにはAWS Step Functionsを利用する

なんとなくわかった気がしたので、実際にマネジメントコンソールから設定してみます。

AWS Batchの設定

ではAWS Batchの設定を行いたいと思います。

ジョブの作成には、ジョブ定義とジョブキューが必要です。なので、この二つを作成します。

しかしジョブ定義の作成にはコンテナを指定する必要があったので、まず初めにコンテナイメージの作成から行なっていきます。

コンテナイメージの作成

ECRに登録するためにローカルで作成したイメージにECR用のタグを設定します。ローカルにあるイメージのタグをtest:1.0とすると

1
$ docker tag test:1.0 xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/test:1.0

というようにしてECR用のタグを設定します。

コンテナレジストリへの登録

ECRに登録するためECRにログインし、先ほど作成したイメージをpushします。

1
2
$ aws ecr get-login-password --region ap-northeast-1 --profile test | docker login --username AWS --password-stdin xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com
$ docker push xxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/test:1.0

ジョブ定義の作成

コンテナイメージをECRに登録できたので、ジョブ定義を作成します。

ジョブ定義に必要な内容は

  • 名前
  • プラットフォーム(EC2 or Fargate)
  • 再試行戦略
    • ジョブの試行回数
  • 実行タイムアウト
  • コンテナプロパティ
    • イメージ
    • コマンドの構文
    • コマンド
    • vCPU
    • メモリ
    • 実行ロール
    • Fargateプラットフォームのバージョン

です。
今回はプラットフォームにFargate、コンテナプロパティのイメージには先ほどECRに登録したイメージを指定します。コンテナプロパティのコマンドにはバッチで実行するコマンドを指定します。

ジョブキューの作成

次にジョブキューを作成します。

ジョブキューの作成には

  • 名前
  • 優先度
  • コンピューティング環境

が必要です。

コンピューティング環境を作成していなかったので、こちらを作成します。

コンピューティング環境の作成

コンピューティング環境の作成では以下の項目を設定します。

  • コンピューティング環境設定
    • コンピューティング環境のタイプ(マネージド or not)
    • コンピューティング環境の名前
  • インスタンスの設定
    • プロビジョニングモデル(Fargateなど)
    • 最大vCPU
  • ネットワーキング
    • VPC ID
    • サブネット

では以下にそれぞれの設定内容を記載します。

コンピューティング環境のタイプ

マネージド型

コンピューティング環境の名前

任意の文字列

プロビジョニングモデル

Fargate

最大vCPU

256

VPC ID

このコンピューティング環境専用のVPCを指定します

サブネット

上記VPCに紐づいたサブネット(パブリック)を指定します。パブリックサブネットにするのはECRへのアクセスを行うためです。

コンピューティング環境の作成ができたら、ジョブキューの作成を完了します。

ジョブの投入

では実際にジョブを作成してバッチを実行してみます。

ジョブから新しいジョブを送信をクリックします。名前は任意ですが、ジョブ定義・ジョブキューは先ほど作成したものを指定します。実行タイムアウトが空欄になっているので最小値の60を指定します。それ以外の項目に関しては、ジョブ定義・ジョブキューの内容が反映されています。

では送信ボタンを押して実行しましょう。


エラー発生

少し待ってからダッシュボードで確認すると、FAILEDに1と表示されてしまいました。FAILEDの1がリンクになっていてクリックしてみると、失敗したジョブが表示されました。

失敗したジョブ名がリンクになっていたのでクリックすると、ジョブの詳しい情報が表示されました。

ステータス理由というところに、エラー内容が記載されていました。

1
ResourceInitializationError: unable to pull secrets or registry auth: pull command failed: : signal: killed

なにかしらの原因でイメージが引っ張ってこれなかったということでしょうか。エラー内容から検索してみます。

ECR接続のためのルーティング設定

エラーメッセージで調査したところ、やはりECRからコンテナイメージをpullできなかったときに表示されるエラーメッセージでした。

ECRからコンテナイメージを取得するための方法が公式ドキュメントに載っていました。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ecs-pull-container-api-error-ecr/

今回の場合はFargateを利用していて、パブリックサブネット(のつもり)だったので、サブネットの設定で自動割り当てパブリックIPが有効になっているかを確認したのですが、有効になっていました。

もう少し調べてみると、パブリックサブネットと呼べるネットワーク設定の一つに、ルーティングでインターネットゲートウェイを向いていることと書かれていました。調べてみるとデフォルトルートが指定されておらず、ローカルのルーティングしか設定されていませんでした。

VPCのルートテーブルのデフォルトルート(0.0.0.0/0)にインターネットゲートウェイを設定しました。

実行確認

再度ジョブを実行してみると、今度は無事SUCCEEDEDになりました。

まとめ

AWS BatchでDjangoのカスタムコマンドを実行することができました。

次回は今回手動で実行していたジョブをイベントをトリガーに実行するようにしてみようと思います。

参考図書

AWS認定資格試験テキスト AWS認定ソリューションアーキテクト - アソシエイト 改訂第2版

Djangoでカスタムコマンドを作成する

背景

Djangoでバッチを実行することになりました。

Railsの場合はRakeタスクがあります。Djangoの場合はどのように行うのか調べて試してみました。

既存のカスタムコマンドの確認

Djangoでコマンドを追加するには、manage.pyを使ったカスタムコマンドと呼ばれる処理を追加することになります。もともとDjangoにはmanage.pyを利用したコマンドがいくつもあります。一覧で見てみましょう。一覧で見るにはmanage.pyに引数をつけずに実行します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
$ docker-compose run --rm web python manage.py
Starting django_db_1 ... done
Creating django_web_run ... done

Type 'manage.py help <subcommand>' for help on a specific subcommand.

Available subcommands:

[auth]
changepassword
createsuperuser

[contenttypes]
remove_stale_contenttypes

[django]
check
compilemessages
createcachetable
dbshell
diffsettings
dumpdata
flush
inspectdb
loaddata
makemessages
makemigrations
migrate
sendtestemail
shell
showmigrations
sqlflush
sqlmigrate
sqlsequencereset
squashmigrations
startapp
startproject
test
testserver

[sessions]
clearsessions

[staticfiles]
collectstatic
findstatic
runserver

runserverstartprojectなど見慣れたコマンドもいくつかありますが、ほとんど知らないコマンドです。こんなにあるんですね。

[]で囲まれているのはアプリケーション名でしょうか。settings.pyINSTALLED_APPSに指定されている名前と一致しています。

カスタムコマンドを追加する

カスタムコマンドの追加方法はこちらに記載されています。正確にはカスタムマネジメントコマンドなんですね。

実行ファイルを配置する

先ほどの公式サイトには以下のようにディレクトリ階層が書かれています。

1
2
3
4
5
6
7
8
9
10
11
polls/
__init__.py
models.py
management/
__init__.py
commands/
__init__.py
_private.py
closepoll.py
tests.py
views.py

ですので、アプリケーションディレクトリの下にmanagementディレクトリを作成し、その下にcommandsディレクトリを作成して、その下に実行するファイルを置く感じのようです。

実際に作成してみます。

1
2
3
$ cd sample_application
$ mkdir -p management/commands/
$ touch management/commands/dummy.py

これで実行ファイルを配置することができました。

実行ファイルを実装する

カスタムコマンドの実行方法についても、先ほどの公式サイトに記載されています。

例ではBaseCommandCommandErrorをimportしていますが動かすだけであればBaseCommandのみでよさそうです。今回は単純なサンプルを作って実行できるところまで試したいので、BaseCommandのみ利用したいと思います。

(タスクが正常に動作しなかった場合はCommandError例外をあげて知らせるということだと思います)

ということで、dummy.pyを実装してみました

1
2
3
4
5
6
7
8
9
10
from django.core.management.base import BaseCommand

class Command(BaseCommand):
help = 'Dummy command'

def add_arguments(self, parser):
pass

def handle(self, *args, **options):
print("execute Dummy command")

では実行してみます。

カスタムコマンドを実行する

それでは実行してみましょう。

1
2
3
4
$ docker-compose run --rm web python manage.py dummy
Creating django_web_run ... done
Unknown command: 'dummy'
Type 'manage.py help' for usage.

おっと、実行に失敗してしまいました…どこか設定が足りないようなので、調べてみます。

INSTALLED_APPへの追加

どの設定が足りないのかを調べていたところ、公式サイトにあまり目立たない感じで以下のように書かれていました。

1
In this example, the closepoll command will be made available to any project that includes the polls application in INSTALLED_APPS.

この例の場合は、pollsINSTALLED_APPSに設定すると有効になります、的なことが書いてあるのかと思います。

ということでINSTALLED_APPSに追加します

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git diff sample_application/settings.py
diff --git a/sample_application/settings.py b/sample_application/settings.py
index b2f36d7..22ccbe3 100644
--- a/sample_application/settings.py
+++ b/sample_application/settings.py
@@ -37,6 +37,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
+ 'sample_application'
]

MIDDLEWARE = [

では実行してみます

1
2
3
$ docker-compose run --rm web python manage.py dummy
Creating django_web_run ... done
execute Dummy command

無事実行できました!

まとめ

今回カスタムコマンドの追加方法を学びました。INSTALLED_APPSに追加していなかったところ以外はスムーズでした。通常はアプリケーションは追加されているはずなので、わざわざINSTALLED_APPSに追加するという説明はほとんど書かれていません。参考図書の実践Django Pythonによる本格Webアプリケーション開発にも、カスタムコマンドの追加に関しては3ページくらいさいてあるのですが(280ページ、管理コマンドの追加)、INSTALLED_APPSに追加しないと有効にならないとは記載されていません。わたしみたいな初心者しかここでは躓かないのかもしれませんね。

次回はこのコンテナを使ってカスタムコマンドをAWS Batchで実行しようと思います。

参考図書

Djangoで各環境ごとの設定を行う

背景

Djangoでアプリケーションを開発するための準備として情報をいろいろ集めています。

アプリケーションを稼働させる環境として、ローカルの開発環境(development)とステージング環境(staging)と本番環境(production)があります。

Djangoではどのように環境ごとの設定をするのだろう?と思ったので調べてみることにしました。

Railsの場合

RailsではRAILS_ENVという環境変数があり、RAILS_ENVに環境名を設定します。また、設定ファイルはRAILS_ENVで設定した環境名により、設定値が変えられるようになっています。また、そういった環境ごとで設定を分けるのをサポートしてくれるgemもあります。アプリケーションもサポートしてくれていますし、それをサポートするgemもあるのはすばらしいですね。

Djangoの場合

調べてみてもあまり情報は出てきませんでした。Railsよりは情報量が多くなかったです。

困っていたところ、この前購入した実践Django Pythonによる本格Webアプリケーション開発9.9 設定ファイルの分割にその方法が載っていることに気づきました。

DjangoではDJANGO_SETTGINS_MODULEという環境変数に、設定ファイル(デフォルトでsettings.py)を指定することで、環境ごとの設定を行うことができそうです。

以下のような感じで行います。

1
$ DJANGO_SETTING_MODULE=project.production_settings python manage.py runserver

Railsでは環境名でしたが、Djangoでは設定ファイル自体を指定するようですね。環境名ではなく設定ファイルなので、設定をそのファイルにすべて記載しないといけなさそうで、だいぶ大きくなってしまうイメージがありますが、実際に実装していってからその問題にあたったら考えたいと思います。

ちなみに、--settingsオプションでも指定できるようです。

1
$ python manage.py runserver --settings=project.production_settings

コンテナの利用の際などは環境変数を渡すことが多いと思いますので、環境変数の方を利用するということで大丈夫かと思います。

まとめ

Webアプリケーションフレームワークでは環境ごとの設定をサポートしているものがほとんどだと思います。Djangoでのサポート方法を調べてみました。

実際に設定ファイルを書いてみて問題が出てきたらまた共有したいと思います。

参考図書

Pipenv入門

背景

前回Dockerでモジュールを利用するにはdocker volumeを利用する必要があるということを記載しました。

pythonのモジュール管理でPipenvというRubyのbundlerに似ているツールがあるということで、これを調べてみようと思います。

Pipenvとは

ドキュメントにはこう記載されています。

Pipenv は、全てのパッケージングの世界 (bundler、composer、npm、cargo、yarnなどなど。) における最高のものをPythonの世界にもたらすことを目的としたツールです。

また、以下のようにも書いてあります。

Pipenvは、手動でパッケージのインストールおよびアンインストールを行うのと同じように Pipfile に対してパッケージの追加および削除を行うのに加え、自動でプロジェクト用の仮想環境を作成し管理します。 またPipenvは、いかなるときも重要な Pipfile.lock を生成し、これを利用しビルドが常に同じ結果になるようにします。

ほぼRubyのbundlerと一緒ですかね。では実際に使ってみます。

Pipenvのインストール

以前利用していたDockerの環境でインストールしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$ docker-compose run --rm web pip install pipenv
Starting django_db_1 ... done
Creating django_web_run ... done
Collecting pipenv
Downloading pipenv-2021.5.29-py2.py3-none-any.whl (3.9 MB)
|████████████████████████████████| 3.9 MB 107 kB/s
Collecting certifi
Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
|████████████████████████████████| 145 kB 180 kB/s
Collecting virtualenv-clone>=0.2.5
Downloading virtualenv_clone-0.5.6-py3-none-any.whl (6.6 kB)
Requirement already satisfied: setuptools>=36.2.1 in /usr/local/lib/python3.9/site-packages (from pipenv) (57.0.0)
Requirement already satisfied: pip>=18.0 in /usr/local/lib/python3.9/site-packages (from pipenv) (21.1.3)
Collecting virtualenv
Downloading virtualenv-20.6.0-py2.py3-none-any.whl (5.3 MB)
|████████████████████████████████| 5.3 MB 189 kB/s
Collecting backports.entry-points-selectable>=1.0.4
Downloading backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl (6.2 kB)
Collecting distlib<1,>=0.3.1
Downloading distlib-0.3.2-py2.py3-none-any.whl (338 kB)
|████████████████████████████████| 338 kB 91 kB/s
Collecting filelock<4,>=3.0.0
Downloading filelock-3.0.12-py3-none-any.whl (7.6 kB)
Collecting six<2,>=1.9.0
Downloading six-1.16.0-py2.py3-none-any.whl (11 kB)
Collecting platformdirs<3,>=2
Downloading platformdirs-2.2.0-py3-none-any.whl (13 kB)
Installing collected packages: six, platformdirs, filelock, distlib, backports.entry-points-selectable, virtualenv-clone, virtualenv, certifi, pipenv
Successfully installed backports.entry-points-selectable-1.1.0 certifi-2021.5.30 distlib-0.3.2 filelock-3.0.12 pipenv-2021.5.29 platformdirs-2.2.0 six-1.16.0 virtualenv-20.6.0 virtualenv-clone-0.5.6
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.1.3; however, version 21.2.1 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.

無事インストールできましたが、警告が2つほど出てますね。pipは結構頻繁にアップデートするんですかね?とりあえずアップデートしておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker-compose run --rm web pip install --upgrade pip
Creating django_web_run ... done
Requirement already satisfied: pip in /usr/local/lib/python3.9/site-packages (21.1.3)
Collecting pip
Downloading pip-21.2.1-py3-none-any.whl (1.6 MB)
|████████████████████████████████| 1.6 MB 39 kB/s
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 21.1.3
Uninstalling pip-21.1.3:
Successfully uninstalled pip-21.1.3
Successfully installed pip-21.2.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

アップグレードできました。

念のため一覧表示で確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ docker-compose run --rm web pip list
Creating django_web_run ... done
Package Version
--------------------------------- ---------
asgiref 3.3.4
backports.entry-points-selectable 1.1.0
certifi 2021.5.30
distlib 0.3.2
Django 3.2.4
filelock 3.0.12
mysqlclient 2.0.3
pip 21.2.1
pipenv 2021.5.29
platformdirs 2.2.0
pytz 2021.1
setuptools 57.0.0
six 1.16.0
sqlparse 0.4.1
virtualenv 20.6.0
virtualenv-clone 0.5.6
wheel 0.36.2

無事Pipenvもインストールされています。バージョン番号が年月日なんですね。

Pipfileの作成

ではPipfileを作成します。こちらによると、requirements.txtがあれば、その内容からPipfileを作成してくれるようです。やってみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ docker-compose run --rm web python -m pipenv install
Creating django_web_run ... done
Creating a virtualenv for this project...
Pipfile: /code/Pipfile
Using /usr/local/bin/python3.9 (3.9.5) to create virtualenv...
⠇ Creating virtual environment...created virtual environment CPython3.9.5.final.0-64 in 518ms
creator CPython3Posix(dest=/root/.local/share/virtualenvs/code-_Py8Si6I, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
added seed packages: pip==21.1.3, setuptools==57.1.0, wheel==0.36.2
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

✔ Successfully created virtual environment!
Virtualenv location: /root/.local/share/virtualenvs/code-_Py8Si6I
requirements.txt found, instead of Pipfile! Converting...
✔ Success!
Warning: Your Pipfile now contains pinned versions, if your requirements.txt did.
We recommend updating your Pipfile to specify the "*" version, instead.
Pipfile.lock not found, creating...
Locking [dev-packages] dependencies...
Locking [packages] dependencies...
Building requirements...
Resolving dependencies...
✔ Success!
Updated Pipfile.lock (1644d3)!
Installing dependencies from Pipfile.lock (1644d3)...
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 5/5 — 00:00:04
To activate this project's virtualenv, run pipenv shell.
Alternatively, run a command inside the virtualenv with pipenv run.

実行が終わりました。PipfilePipfile.lockも作成されています。

virtualenvについて

出力されたメッセージをみていて、気になる点がいくつかあります。

1
2
✔ Successfully created virtual environment! 
Virtualenv location: /root/.local/share/virtualenvs/code-_Py8Si6I

仮想環境を作成したと表示がありますが、仮想環境はdocker volumeを使っていないので消えてしまっている可能性が高いです。確認してみます。

仮想環境のパスを確認するコマンドがあるようなのでそれを実行してみます。

1
2
3
4
$ docker-compose run --rm web python -m pipenv --venv
Creating django_web_run ... done
No virtualenv has been created for this project(/code) yet!
Aborted!

やはりダメでした…仮想環境を使わずにインストールする方法はないかと探してみたところ、--systemというオプションがあるようです。

https://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html#pipenv-install

やってみます

1
2
3
4
$ docker-compose run --rm web python -m pipenv install --system
Creating django_web_run ... done
Installing dependencies from Pipfile.lock (1644d3)...
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 0/0 — 0

先ほどインストールしたのでインストール済だからでしょうか。パッケージがインストールされた感じはありません。一度全てアンインストールしてみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$ docker-compose run --rm web python -m pipenv uninstall --system --all
Creating django_web_run ... done
Creating a virtualenv for this project...
Pipfile: /code/Pipfile
Using /usr/local/bin/python3.9 (3.9.5) to create virtualenv...
⠇ Creating virtual environment...created virtual environment CPython3.9.5.final.0-64 in 521ms
creator CPython3Posix(dest=/root/.local/share/virtualenvs/code-_Py8Si6I, clear=False, no_vcs_ignore=False, global=False)
seeder FromAppData(download=False, pip=bundle, setuptools=bundle, wheel=bundle, via=copy, app_data_dir=/root/.local/share/virtualenv)
added seed packages: pip==21.1.3, setuptools==57.1.0, wheel==0.36.2
activators BashActivator,CShellActivator,FishActivator,PowerShellActivator,PythonActivator,XonshActivator

✔ Successfully created virtual environment!
Virtualenv location: /root/.local/share/virtualenvs/code-_Py8Si6I
Un-installing all [dev-packages] and [packages]...
Found 0 installed package, skip purging.
Environment now purged and fresh!

なぜか仮想環境が立ち上がってしまっています…アンインストール時は--systemオプションを正しく反映できてないようです…

仕方ないので、pipコマンドでアンインストールしてみます

1
2
3
4
5
6
7
8
9
10
11
12
$ docker-compose run --rm web python -m pip uninstall django
Creating django_web_run ... done
Found existing installation: Django 3.2.4
Uninstalling Django-3.2.4:
Would remove:
/usr/local/bin/django-admin
/usr/local/bin/django-admin.py
/usr/local/lib/python3.9/site-packages/Django-3.2.4.dist-info/*
/usr/local/lib/python3.9/site-packages/django/*
Proceed (Y/n)? Y
Successfully uninstalled Django-3.2.4
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

アンインストールできたかどうかを確認します

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ docker-compose run --rm web python -m pip list
Creating django_web_run ... done
Package Version
--------------------------------- ---------
asgiref 3.4.1
backports.entry-points-selectable 1.1.0
certifi 2021.5.30
distlib 0.3.2
filelock 3.0.12
mysqlclient 2.0.3
pip 21.2.1
pipenv 2021.5.29
platformdirs 2.2.0
pytz 2021.1
setuptools 57.0.0
six 1.16.0
sqlparse 0.4.1
virtualenv 20.6.0
virtualenv-clone 0.5.6
wheel 0.36.2

djangoがなくなっていることがわかります。では--systemオプションを指定してインストールしてみましょう。

1
2
3
4
$ docker-compose run --rm web python -m pipenv install --system
Creating django_web_run ... done
Installing dependencies from Pipfile.lock (1644d3)...
🐍 ▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉▉ 1/1 —

インストールされたことを確認します

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ docker-compose run --rm web python -m pip list
Creating django_web_run ... done
Package Version
--------------------------------- ---------
asgiref 3.4.1
backports.entry-points-selectable 1.1.0
certifi 2021.5.30
distlib 0.3.2
Django 3.2.4
filelock 3.0.12
mysqlclient 2.0.3
pip 21.2.1
pipenv 2021.5.29
platformdirs 2.2.0
pytz 2021.1
setuptools 57.0.0
six 1.16.0
sqlparse 0.4.1
virtualenv 20.6.0
virtualenv-clone 0.5.6
wheel 0.36.2

アンインストール時はpip uninstallで行うのがよさそうです

Pipenvを利用した開発フロー

Pipfile, Pipfile.lockの扱い

Pipfile、Pipfile.lockはソースコード管理ツールで管理するのがよさそうです。初めてプロジェクトをチェックアウトしたメンバーはこれらのファイルを元にpipenv installを行います。こちらにも記載があります。

開発環境と本番環境

開発環境では--devオプションを指定、本番環境では指定しないようにします。

Docker環境でのインストール

Docker環境ではシステムのpipを利用すればよいので、pipenv install --systemとします。すると、Pipfile.lockの内容でインストールが行われます。ただし、アンインストールができないので、その場合はpip uninstall パッケージ名とします。

まとめ

Pythonのパッケージ管理ツールのPipenvについて調べてみました。

Dockerで利用するのが前提だったため、仮想環境を用いないオプションを探したりするのに少し時間がかかりました(ドキュメントを読むのは大事ですね)。また、アンインストールがうまくいかない点などスムーズにいかない点がいくつかありました。

Rubyに慣れている自分にとっては、Pythonのパッケージ管理システムは難しかったです。bundlerさえわかっていれば済むRubyは素敵だなと思いました。Pythonのパッケージ管理システムはまだ発展途上という感じでしょうか。

当面はPipenvを使ってチーム開発を行なっていこうと思います。

Dockerでのpythonモジュールの管理

背景

前回pythonのモジュール管理をRubyと比較しながら学びました。pythonにはvenvというモジュールでプロジェクトごとにモジュールを分離できるということを学びました。

しかし、ローカルPCではなくDockerを使う場合はそもそもモジュールの分離を検討しなくてもよいのではないか?と思ったので、Dockerでのモジュール管理について考えていきたいと思います。

現在のDockerfile

以前利用していたDockerfileはこんな感じでした

1
2
3
4
5
6
7
8
FROM python:3.9.5-alpine
ENV PYTHONUNBUFFERED 1
RUN apk update && apk add mysql-client mysql-dev gcc libc-dev
RUN mkdir /code
WORKDIR /code
ADD requirements.txt /code/
RUN pip install -r requirements.txt
ADD . /code/

モジュールのインストールに関しては7行目の

RUN pip install -r requirements.txt

で行なっています。

requirements.txtは

1
2
Django==3.2.4
mysqlclient

でした。イメージのビルド時にDjango3.2.4とmysqlclientとそれに依存したパッケージがインストールされます。

インストールされたパッケージの確認

現在インストールされているパッケージの確認を行います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ docker run -it image_name /bin/sh
/code #
/code # which pip
/usr/local/bin/pip
/code # pip list
Package Version
----------- -------
asgiref 3.3.4
Django 3.2.4
mysqlclient 2.0.3
pip 21.1.2
pytz 2021.1
setuptools 57.0.0
sqlparse 0.4.1
wheel 0.36.2
WARNING: You are using pip version 21.1.2; however, version 21.1.3 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.

指定したのはDjangoとmysqlclientのみでしたが、依存関係でその他のパッケージがいくつかインストールされていることがわかります。

現在のdocker-compose.yml

現在のdocker-compose.ymlは以下のようになっています。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
version: '3'

services:
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: django
MYSQL_PASSWORD: django
MYSQL_DATABASE: django
ports:
- 33060:3306
volumes:
- mysql:/var/lib/mysql
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db

volumes:
mysql:
driver: local

volumesはmysqlのストレージをDocker内に持っているのみです。

モジュールのインストール、アップデート時の動作

なんとなく予想できますが、モジュールのインストール、アップデートを試してみます。

モジュールのインストール

モジュールのインストールを行なってみます。今回はhttpクライアントライブラリのRequestsをインストールしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$ docker-compose run --rm web python -m pip install requests
Creating django_web_run ... done
Collecting requests
Downloading requests-2.26.0-py2.py3-none-any.whl (62 kB)
|████████████████████████████████| 62 kB 741 kB/s
Collecting idna<4,>=2.5
Downloading idna-3.2-py3-none-any.whl (59 kB)
|████████████████████████████████| 59 kB 2.6 MB/s
Collecting certifi>=2017.4.17
Downloading certifi-2021.5.30-py2.py3-none-any.whl (145 kB)
|████████████████████████████████| 145 kB 7.9 MB/s
Collecting urllib3<1.27,>=1.21.1
Downloading urllib3-1.26.6-py2.py3-none-any.whl (138 kB)
|████████████████████████████████| 138 kB 7.0 MB/s
Collecting charset-normalizer~=2.0.0
Downloading charset_normalizer-2.0.3-py3-none-any.whl (35 kB)
Installing collected packages: urllib3, idna, charset-normalizer, certifi, requests
Successfully installed certifi-2021.5.30 charset-normalizer-2.0.3 idna-3.2 requests-2.26.0 urllib3-1.26.6
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv
WARNING: You are using pip version 21.1.2; however, version 21.1.3 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.

警告が出ていますが、無事インストールできたようです。ではpip listで一覧を表示してみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker-compose run --rm web pip list
Creating django_web_run ... done
Package Version
----------- -------
asgiref 3.3.4
Django 3.2.4
mysqlclient 2.0.3
pip 21.1.2
pytz 2021.1
setuptools 57.0.0
sqlparse 0.4.1
wheel 0.36.2
WARNING: You are using pip version 21.1.2; however, version 21.1.3 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.

インストールしたパッケージは消えてなくなっています。

モジュールのアップデート

結果はなんとなくわかりますが、警告が出ていたpipをアップデートしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker-compose run --rm web python -m pip install --upgrade pip
Creating django_web_run ... done
Requirement already satisfied: pip in /usr/local/lib/python3.9/site-packages (21.1.2)
Collecting pip
Downloading pip-21.1.3-py3-none-any.whl (1.5 MB)
|████████████████████████████████| 1.5 MB 5.9 MB/s
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 21.1.2
Uninstalling pip-21.1.2:
Successfully uninstalled pip-21.1.2
Successfully installed pip-21.1.3
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv

無事21.1.3にアップデートされたように見えます。

pip listで確認します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker-compose run --rm web python -m pip list
Creating django_web_run ... done
Package Version
----------- -------
asgiref 3.3.4
Django 3.2.4
mysqlclient 2.0.3
pip 21.1.2
pytz 2021.1
setuptools 57.0.0
sqlparse 0.4.1
wheel 0.36.2
WARNING: You are using pip version 21.1.2; however, version 21.1.3 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.

予想通り21.1.2に戻っています。

Docker Volumeの利用

モジュールのインストール、アップデートを行なったところで、保存しておくストレージがないため、コンテナを停止すると次回起動時はイメージをビルドした時の状態になっています。

その対応としてDocker Volumeを利用します。

モジュールインストールディレクトリの確認

まずはじめにモジュールがどこにインストールされているかを確認します。

モジュールのインストール先を確認するにはpip showコマンドを利用します。Djangoのパッケージがどこにインストールされているのかをみてみます。

1
2
3
4
5
6
7
8
9
10
11
12
$ docker-compose run --rm web pip show django
Creating django_web_run ... done
Name: Django
Version: 3.2.4
Summary: A high-level Python Web framework that encourages rapid development and clean, pragmatic design.
Home-page: https://www.djangoproject.com/
Author: Django Software Foundation
Author-email: foundation@djangoproject.com
License: BSD-3-Clause
Location: /usr/local/lib/python3.9/site-packages
Requires: asgiref, pytz, sqlparse
Required-by:

Locationにインストールディレクトリが表示されています。その他依存関係なども表示されていて便利ですね!

念のため別のパッケージでも試してみます。

1
2
3
4
5
6
7
8
9
10
11
12
$ docker-compose run --rm web pip show mysqlclient
Creating django_web_run ... done
Name: mysqlclient
Version: 2.0.3
Summary: Python interface to MySQL
Home-page: https://github.com/PyMySQL/mysqlclient
Author: Inada Naoki
Author-email: songofacandy@gmail.com
License: GPL
Location: /usr/local/lib/python3.9/site-packages
Requires:
Required-by:

Djangoと同じパスでした。ということはこのディレクトリにボリュームを割り当てれば良さそうです。

Volumeを利用するようdocker-compose.ymlを変更

/usr/local/lib/python3.9/site-packagesにvolumeを割り当ててみます。

docker-compose.ymlのwebの箇所

1
2
3
4
5
6
7
8
9
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
links:
- db

1
2
3
4
5
6
7
8
9
10
web:
build: .
command: python3 manage.py runserver 0.0.0.0:8000
volumes:
- .:/code
- site-packages:/usr/local/lib/python3.9/site-packages
ports:
- "8000:8000"
links:
- db

とし、volumeにも追加します

1
2
3
4
5
volumes:
mysql:
driver: local
site-packages:
driver: local

この設定で試してみます。

動作確認

さきほどと同様にpip listから始めます

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ docker-compose run --rm web python -m pip list
Creating django_web_run ... done
Package Version
----------- -------
asgiref 3.3.4
Django 3.2.4
mysqlclient 2.0.3
pip 21.1.2
pytz 2021.1
setuptools 57.0.0
sqlparse 0.4.1
wheel 0.36.2
WARNING: You are using pip version 21.1.2; however, version 21.1.3 is available.
You should consider upgrading via the '/usr/local/bin/python -m pip install --upgrade pip' command.

pipをアップデートしてみます。

1
2
3
4
5
6
7
8
9
10
11
12
13
$ docker-compose run --rm web python -m pip install --upgrade pip
Creating django_web_run ... done
Requirement already satisfied: pip in /usr/local/lib/python3.9/site-packages (21.1.2)
Collecting pip
Downloading pip-21.1.3-py3-none-any.whl (1.5 MB)
|████████████████████████████████| 1.5 MB 3.3 MB/s
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 21.1.2
Uninstalling pip-21.1.2:
Successfully uninstalled pip-21.1.2
Successfully installed pip-21.1.3
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv

無事できました。

pip listでアップデートされたままかどうか確認します。

1
2
3
4
5
6
7
8
9
10
11
12
$ docker-compose run --rm web python -m pip list
Creating django_web_run ... done
Package Version
----------- -------
asgiref 3.3.4
Django 3.2.4
mysqlclient 2.0.3
pip 21.1.3
pytz 2021.1
setuptools 57.0.0
sqlparse 0.4.1
wheel 0.36.2

アップデートされたままになっていました!無事volumeが利用できています!

まとめ

Dockerを利用する場合、パッケージのインストールディレクトリはvolumeを利用しないと変更が保存されないので、volumeを利用します。

開発の途中でパッケージのインストールが必要になった場合はインストールし、pip freezerequirements.txtを更新し、コミットします。

他のメンバーはそれをチェックアウトして、pip install -r requirements.txtを行います。

このフローで開発を回していくことができるようになりました。

次回は、今回よく表示されていた警告

1
WARNING: Running pip as root will break packages and permissions. You should install packages reliably by using venv: https://pip.pypa.io/warnings/venv

について調べてみようと思います。rootで実行するのはパーミッションを壊してしまうのでよくないということだと思いますが、venvとの関連がいまいちわかっていません…前回venvについて調べておいてよかったですが、次回はこの問題を解決していこうと思います。