- 投稿日:2020-04-30T23:43:55+09:00
【�database.yml】DBをDockerとrails server両方で使えるように�設定
Dokerで開発時に、
docker-compose runやdocker-compose runよりも早いrails serverで一時的に動作確認をしたい場合があるかと思う。
そういった場合にも、以下のconfig/database.yml内の記述だけで対応することができる。検証環境
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.3 BuildVersion: 19D76$ ruby -v ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin19]$ rails -v Rails 5.2.4.2database.ymlについて
まず、database.ymlとは
config/database.yml(例)default: &default adapter: mysql2 encoding: utf8 collation: utf8_general_ci pool: 5 host: <%= ENV['MYSQL_HOST'] || 'localhost' %> username: <%= ENV['MYSQL_USERNAME'] || 'root' %> password: <%= ENV['MYSQL_PASSWORD'] || '' %> socket: /tmp/mysql.sock主な内容
adapter: 使用するデータベースの種類(postgresql, mysql2等)
encoding: 文字コード
collation: MySQLの文字列と照合順序(ソート順)、”文字コード言語名比較法”で構成される
pool: 確保する接続プールの数
host: データベースが動作しているホスト名またはIPアドレス
username,password: データベースに接続するユーザー名・パスワード
socket: DB通信の接続口
比較演算子: ||
orと同じ働きをする。
Ruby 2.7.0 リファレンスマニュアル 演算子式文法:
式 `||' 式
式 or 式
左辺を評価し、結果が真であった場合にはその値を返します。左辺の評価結果が偽であった場合には右辺を評価しその評価結果を返します。config/database.ymlのhost,username,passwordの部分をこれで書くことで、
ENV['MYSQL_HOST']等の環境変数がない場合に、localhost等を返してくれる。終わりに。
最後まで読んで頂きありがとうございます
転職の為、未経験の状態からRailsを学習しております。正しい知識を着実に身に着け、実力のあるエンジニアになりたいと考えています。継続して投稿していく中で、その為のインプットも必然的に増え、成長に繋がるかと考えています。
今現在、初心者だからといって言い訳はできないですが、投稿の内容に間違っているところや、付け加えるべきところが多々あるかと思いますので、ご指摘頂けると幸いです。この記事を読んで下さりありがとうございました。参考にさせて頂いた記事
- 投稿日:2020-04-30T22:02:36+09:00
初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)StatfulSet編
背景
個人的にインフラの知識以上にこれからのアプリケーションが動く環境を作ってデプロイしたりしてこれからの知識を身に着けたい。そしてより一層、自分の知識のアップデートをしたいと思いました。
その中でこの本に出会い、これから少しずつやったことを残し、未来の自分への手紙としてもあり、見つめ直せればと思いました。
引用や参考と今回の自分の勉強用の書籍の紹介
技術評論社『Kubernetes実践入門』のサンプルコード
Kubernetes実践入門 プロダクションレディなコンテナ&アプリケーションの作り方
実際の学びについて
書籍を読みながら、章ごとに少しずつ進めていきたいと思います。
GitHub のソースコードも使いながら学んで行きたいと思います。
この章の勉強は本当に書籍の写経が主になるかもしれません・・・勉強開始
- StatufulSet を使った MySQL を定義 ※いまここ
- MySQL のデータ格納用に内部ストレージを割り当て
- 設定ファイルを Master、Slave 用に設定し配置
- バックアップ用に外部ストレージを割り当て
- Master-Slave 間でデータを同期
StatefulSet を使った MySQL を定義
以前写経で学んだ、 ConfigMap / Secret マニュフェストを使って、MySQL のコンフィグ情報を各 yaml ファイルに定義します。
cm.yamlapiVersion: v1 data: MYSQL_DATABASE: mattermost MYSQL_USER: myuser kind: ConfigMap metadata: creationTimestamp: null name: common-envsecret.yamlapiVersion: v1 data: MYSQL_PASSWORD: bXlwYXNzd29yZA== MYSQL_ROOT_PASSWORD: cm9vdHBhc3N3b3Jk kind: Secret metadata: creationTimestamp: null name: common-envmysql-sts.yamlapiVersion: apps/v1 kind: StatefulSet metadata: name: mysql spec: serviceName: mysql selector: matchLabels: app: mysql updateStrategy: type: RollingUpdate replicas: 2 template: metadata: labels: app: mysql spec: initContainers: - name: init-mysql image: k8spracticalguide/mysql:5.7.22 command: ["bash", "/mnt/scripts/setup.sh"] volumeMounts: - name: confd mountPath: /mnt/conf.d - name: scripts mountPath: /mnt/scripts - name: initdb mountPath: /mnt/initdb containers: - name: mysql image: k8spracticalguide/mysql:5.7.22 envFrom: - configMapRef: name: common-env - secretRef: name: common-env volumeMounts: - name: data mountPath: /var/lib/mysql - name: initdb mountPath: /docker-entrypoint-initdb.d - name: confd mountPath: /etc/mysql/conf.d - name: backup mountPath: /mnt/backup volumes: - name: initdb emptyDir: {} - name: confd emptyDir: {} - name: scripts configMap: name: mysql-scripts - name: backup persistentVolumeClaim: claimName: backup-mysql volumeClaimTemplates: - metadata: name: data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 1Giマニュフェストを適用$ kubectl apply -f cm.yaml -f secret.yaml -f mysql-sts.yaml configmap/common-env created secret/common-env created statefulset.apps/mysql created適用されているのを確認$ kubectl get statefulsets NAME READY AGE mysql 2/2 74s $ kubectl get po NAME READY STATUS RESTARTS AGE mysql-0 1/1 Running 0 77s mysql-1 1/1 Running 0 73sHeadless Service を定義する
mysql-svc.yamlapiVersion: v1 kind: Service metadata: name: mysql labels: app: mysql spec: ports: - port: 3306 name: mysql clusterIP: None # None にすることで Headless Serviceになる selector: app: mysql適用されているのを確認$ kubectl apply -f mysql-svc.yaml service/mysql created $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h mysql ClusterIP None <none> 3306/TCP 7sちゃんと動いているか確認する
$ kubectl get po -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mysql-0 1/1 Running 0 5m3s 10.1.1.9 docker-desktop <none> <none> mysql-1 1/1 Running 0 4m59s 10.1.1.10 docker-desktop <none> <none> kubectl run -ti --image=k8spracticalguide/busybox:1.28 dns-test --restart=Never --rm /bin/sh If you don't see a command prompt, try pressing enter. / # nslookup mysql-0.mysql Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: mysql-0.mysql Address 1: 10.1.1.9 mysql-0.mysql.default.svc.cluster.local / # nslookup mysql-1.mysql Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: mysql-1.mysql Address 1: 10.1.1.10 mysql-1.mysql.default.svc.cluster.local次は 3.7.5 章をやっていきます。
- StatufulSet を使った MySQL を定義
- MySQL のデータ格納用に内部ストレージを割り当て ※次回
- 設定ファイルを Master、Slave 用に設定し配置
- バックアップ用に外部ストレージを割り当て
- Master-Slave 間でデータを同期
最後に
前回うまくできなかったので、ご迷惑おかけしてしまいました。
次回以降はもっと大胆にうまくできることを祈りながら、写経 がんばります今までの投稿
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)Pod編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)NameSpace 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)Label 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)ReplicaSet 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)Deployment 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)Service 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)ConfigMap 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)Secret 編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)操作編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)体感編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)体感編パート2
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)体感編パート3(Label操作)
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)体感編パート3(OwnerReference 操作)
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)マニュフェスト編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)マニュフェスト(ConfigMap)編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)通信編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)通信編 パート2
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)通信編 パート3
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)通信編 パート4
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)公開編パート1(NodePort)
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)公開編パート2(LoadBalancer)
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)公開編パート3(Ingress)
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)外部ストレージ編
- 初心者のKubernetes入門(書籍 Kubernetes 実践入門の写経から学ぶ)外部ストレージ編パート2
- 投稿日:2020-04-30T21:18:53+09:00
Dockerを知らない素人がWindows10 homeでDocker-Toolboxを使ってDockerコンテナをRunするまでのお話。
前提条件
- Dockerについて何も知らない社会人2年目の社員。
- 上司から「Docker使うから今のうちに勉強しといて」とさっき言われた。。。
- 備忘録とモチベ維持のため、Qiitaでアウトプットしつつ勉強を進める予定。
環境
- 20万で買った4年目のNEC LAVIE(ノートPC)
Dockerとはなんぞや。。。
→コンテナ型の仮想環境を作ること!
仮想環境は、Anacondaで言うとBaseと異なる環境が作れる機能だから、PCベースで言うとPCの内側に別のPCが走ってるイメージ。内側のPCは外側のPCに影響されにくいからどんなPCに乗っけても動いてくれる頼りになるやつなんですね。
コンテナ型というのは、従来の仮想化と比べて良いという理解。従来の仮想化ではOSも含めて仮想化を行ってたけど、ファイル重い(OS分容量必要)し、起動遅いし(OSをたくさん起動するから)で扱いずらかった。これをマシーンリソースがかかるとかオーバーヘッドが生じるとかいう専門用語があるわけです。
コンテナ型は元のOSに乗せられるからファイル数軽いし、起動も早い。開発においては便利なツールなんですね。
従来でも元のOSを「ホストOS」、仮想側を「ゲストOS」なんて呼び分けてるけど、これはDockerでも同じなので覚えておいた方がいい(マウントの設定だったりで混乱する)
ただOSが減る分、元のPCから影響受けたりセキュリティ対策対策もちゃんとしないとだから、いいこと尽くめというわけでもないのは注意が必要ですね。
Docker環境構築するよ!
Dockerにも種類がある!
Docker Community Edition(Docker CE)
- 無償版のDocker
- とはいえ問題なく使える
- Stable版…四半期ごとのリリース。安定したものが使える
- Edge版…月1回のリリース。最新版を使える。
Docker Enterprise Edition(Docker EE)
- 有償版Docker
- Docker社認定のコンテナ・プラグインが使える
- イメージのセキュリティあり
- プライベートリポジトリあり
まぁ自主勉強ならDocker CEのStable版が良さそう。
さあインストールするよ!
インストールと言っても3種類くらいあるので個々人の環境によって選ぼう!
1. Docker for Windows
2. Docker for Mac
3. Docker Toolbox1つ目のはWindowsじゃんやった~インストールしよっと思ったのもつかの間、これは「Windows 10 Pro」しか使えないので注意!しかもハイパーバイザーの設定も必要。出だしから難易度高いなぁ。Docker for Windows 10 Proって改名してもらいたい
2つ目のはMac用らしい...(筆者はマックのこと知らない)
3つ目のは我らがwindows 10 homeでも使えるやつ!早速インストール♪
https://github.com/docker/toolbox/releases
↑GitHubからインストール
このレガシーな雰囲気プンプンな香りに負けること無かれ。
↑見慣れた.exeインストーラー
インストールしていきますよ~不明な発行元を「はい」して、デフォルトもまま突き進めばおk!
↑Docker Quickstart Terminalのショートカットをクリックして実行!
初回起動には時間がかかる。↑これで準備完了!クジラのマークが目印!
Dockerを操作するよ!
まぁまずはversionを観察!
$ docker version
version情報の一覧が出てきます↓$ docker version Client: Version: 19.03.1 API version: 1.40 Go version: go1.12.7 Git commit: 74b1e89e8a Built: Wed Jul 31 15:18:18 2019 OS/Arch: windows/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 19.03.5 API version: 1.40 (minimum version 1.12) Go version: go1.12.12 Git commit: 633a0ea838 Built: Wed Nov 13 07:28:45 2019 OS/Arch: linux/amd64 Experimental: false containerd: Version: v1.2.10 GitCommit: b34a5c8af56e510852c35414db4c1f4fa6172339 runc: Version: 1.0.0-rc8+dev GitCommit: 3e425f80a8c931f88e6d94a8c831b9d5aa481657 docker-init: Version: 0.18.0 GitCommit: fec3683なにはともあれHello World!
docker run hello-worldhello-worldというコンテナが立ち上がります!
$ docker run hello-world Unable to find image 'hello-world:latest' locally latest: Pulling from library/hello-world 0e03bdcc26d7: Pull complete Digest: sha256:8e3114318a995a1ee497790535e7b88365222a21771ae7e53687ad76563e8e76 Status: Downloaded newer image for hello-world:latest Hello from Docker! This message shows that your installation appears to be working correctly. To generate this message, Docker took the following steps: 1. The Docker client contacted the Docker daemon. 2. The Docker daemon pulled the "hello-world" image from the Docker Hub. (amd64) 3. The Docker daemon created a new container from that image which runs the executable that produces the output you are currently reading. 4. The Docker daemon streamed that output to the Docker client, which sent it to your terminal. To try something more ambitious, you can run an Ubuntu container with: $ docker run -it ubuntu bash Share images, automate workflows, and more with a free Docker ID: https://hub.docker.com/ For more examples and ideas, visit: https://docs.docker.com/get-started/Hello from Docker!
- 投稿日:2020-04-30T17:20:30+09:00
kubernetesキホンのキ
1. はじめに
前回の投稿から、ご無沙汰してしまいました。前回、Dockerの導入編ということで、Dockerのインストール方法や、簡易的な使い方をまとめました。
今回は、その上位互換として知られる kubernetes の概念や用語について勉強したことをアウトプットしていきます。
2.kubernetesとは
kubernetesを一言でいうと、「コンテナを管理するためのシステム」です。
ざっくり言うと、「Docker 拡張バージョン」です。Docker は単一マシンの上でコンテナを動作させるシステムでしたが、kubernetes は複数マシン上でコンテナを管理・統合させるためのシステムです。コンテナオーケストレーションといいます。
図2.1 は視覚的にDockerとkubernetesの差分を理解するために図示しました。
Dockerのみだと単一ホスト上で動作するコンテナの管理のみしかできませんが、kubernetesを利用することによって、複数のDockerホストをkubernetesのシステム上で管理することができるようになります。Docker でも Docker Swarm を利用することで複数マシン上でコンテナを管理することができますが、kubernetesの方が機能が充実していて実践に使用されているため、今回は kubernetesを取り扱っています。
3. kubernetes の用語
以下 kubernetes で使われている用語をまとめました。
No リソース名 意味・用途 1 Node ・コンテナを乗せる元のサーバ(物理マシン、VMどちらも) 2 Namespace ・仮想的なクラスタ
・開発者(チーム)それぞれのNamespaceを作ることでメインのNamaspaceを綺麗に保つことができる3 Pod ・コンテナの集合体単位
・デプロイするコンテナの集合体になるので、密結合となるwebサーバ用コンテナとアプリケーションサーバ用コンテナをまとめると有効活用できる4 ReplicaSet ・同じ仕様のPodを複数生成・管理
・Podのみでは単一のPodのデプロイしかできないため、複数のPodをデプロイする際に利用する5 Deployment ・ReplicaSetの世代管理
・実運用では、ほとんどDeploymentの単位でデプロイを管理すること6 Service ・Podにアクセスするための経路定義
・アクセスするPodを制御するために利用する
・L4層レベルでのアクセス制御が可能7 Ingress ・Service公開の口
・L7層レベルでのアクセス制御が可能
・HTTP/HTTPSでのサービス公開をする際はServiceよりIngressをメインに使用する8 ConfigMap ・構成ファイル、コマンドライン引数、環境変数、ポート番号などの設定情報を定義し、Podへ供給する
・うまく活用すると構成の変更や管理が容易にできる9 PersistentVolume ・Podが利用するストレージを定義
・ストレージの実体である10 PersistentVolumeClaim ・ストレージを論理的に抽象化したリソース
・PersistentVolumeを動的に確保する(必要な要領のみ)11 StorageClass ・PersistentVolumeが確保するストレージの種類を定義(HDDやSSD等) 12 StatefulSet ・同じ仕様で一意性のあるPodを複数生成・管理
・継続的にデータを永続化するステートフルアプリケーション管理用リソース13 job ・常駐目的ではない複数(もしくは単一)Podを生成し、正常終了するまで管理するリソース
・大規模計算やバッチ処理などで利用14 Cronjob ・cron記法でスケジュール実行されるjob 15 Secret ・認証情報等の機密データを定義するリソース
・証明書や秘密鍵、パスワードなどの機密情報を管理する16 Role ・Namespace内で操作可能なkubernetesリソースのルールを定義するリソース
・権限の管理に利用する17 RoleBinding ・Roleとkubernetesリソースを利用するユーザーを紐付ける 18 ClusterRole ・クラスタ全体で操作可能なkubernetesリソースをルール定義する 19 ClusterRoleBinding ・ClusterRole と kubernetesリソースを利用するユーザーを紐付ける 20 ServiceAccount ・Pod に kubernetes リソースを操作させる際に利用するユーザー 3.まとめ
今回は、kubernetes の概念と用語についてまとめました。
時間があるときにこの用語を参考に実際に手を動かしながら、kubernetesの使い方を見ていきたいと思います。
その中でkubernetesのどういう部分が人気が高いのか考えていければと思います。うまくまとめられればqiitaにも投稿してみます。
また、最近マイクロサービスアーキテクチャを採用したシステムとkubernetesの相性がいいと言われますが、その意味も気にしながら手を動かしていこうと思います。
参考資料
- 投稿日:2020-04-30T16:57:09+09:00
dockerのコマンドメモ
記事の趣旨
dockerコマンドの覚え書き.
1. dockerのコマンド
docker search 検索キーワードDocker Hubに登録されているイメージを,検索キーワードで検索する.
docker pull イメージ名Docker Hubからイメージを取得する.
docker images保有しているイメージの一覧を表示する.
docker run オプション イメージ名 コマンドイメージを用いてコンテナを起動し,コマンドを実行する.かなりオプションが多いので代表的なものだけ以下に書いていく.全量はこちらを参照すること.
-d:コンテナをバックグラウンドで実行する-i:ホストの標準入力をコンテナの標準入力にアタッチする-t:コンテナに疑似TTYを割り当てる-p xxx:yyy:ホストのxxx番ポートにコンテナのyyyポートを割り当てる--name:コンテナに名前を割り当てる--rm:コンテナ終了時に自動的に
-iとか-tとか入れないとどうなるの?という疑問は,こちらを読めば大体解消すると思う.
docker psコンテナの一覧を表示する.
docker attach コンテナ名コンテナ内のPID-1のプロセスに接続する.離脱する場合は
Ctrl-p + qで.
docker exec オプション コンテナ名 コマンドコンテナ内で新たなプロセスを立ち上げてコマンドを実行する.
docker build オプション パスパスに置いてある
Dockerfileという名称のファイルを用いてイメージをビルドする,オプションは以下.
-f:ビルドファイル名を明示する.-t 名称:タグ:イメージにタグをつける
docker cp ホストパス コンテナ名:パスホストパスに存在するファイルをコンテナの指定パスにコピーする.
docker cp コンテナ名:パス ホストパス先述とは逆に,コンテナの指定パスに存在するファイルをホストの指定パスにコピーする.
- 投稿日:2020-04-30T16:45:41+09:00
Django Sprint #3 ユーザーモデルのカスタマイズ
- Django Sprint #0 イントロダクション
- Django Sprint #1 環境構築
- Django Sprint #2 新規プロジェクトのスタート
- Django Sprint #3 ユーザーモデルのカスタマイズ
- Django Sprint #4 トップページの作成
- Django Sprint #5 汎用ビューとCRUD 前編
- Django Sprint #6 汎用ビューとCRUD 後編
目次
1. Gitの運用
2. 各種設定
3. モデル概論
4. ユーザーモデルと認証、管理者Gitの運用
Gitは初めて使う人にとっては少し難しく感じるかもしれません。その際は、言葉を追うより、「習うより慣れろ」的に実際に使ってみる方が分かりやすいでしょう。もし難しいようならGitを使わなくても開発はできます。
本チュートリアルは GitHub Flow を少し変更して行います。もしチームの別の運用ルールがあるのなら、そちらを優先させてください。
また、GitをGUI上で(コマンドラインからではなく、視覚的に)操作するには
をおすすめします。
試しに、READMEファイル(このプロジェクトの説明などを記入するファイル)を追加してみましょう。
branchとは
ブランチとは作業履歴を枝分かれさせて記録していくためのものです。試しに、以下のコマンドを叩いてみましょう。
$ git branch * master現在はmasterブランチしかないはずです。
2つのブランチ: master と develop
先ほど見たmasterブランチはプロジェクトのメインのブランチです。これを「常にデプロイ(公開)可能なもの」としましょう。つまり、テストも終わった「完成品」のみが許される神聖な場所です。
一方、普段の開発用のブランチをdevelopとします。これは開発用のメインのブランチで、公開はされません。developブランチを切る
このdevelopブランチを作成しましょう。ブランチを切るのは次のコマンドです。
$ git checkout -b develop Switched to a new branch 'develop'一応ブランチの一覧を見ると、やはり
$ git branch * develop masterこのようになっています。*は今いるブランチを指します。
これをリモートに反映させましょう。$ git push -u origin developオプション
-uにより、ローカルリポジトリの現在のブランチの上流をorigin developに規定します。これを一度設定すると以後は$ git pushのみでリモートのdevelopブランチにプッシュされることになります。
一度GitHubのページでdevelopブランチが正しく生成されているかどうか確認してみましょう。実際の開発フロー
実際の開発はほとんど以下の繰り返しです。
git pullでリモートの変更をローカルに反映git checkout -bでローカルに機能ブランチを作成git addとgit commitで変更をローカルの機能ブランチに反映git pushでローカル機能ブランチをリモートにアップ- pull request を作成し、機能ブランチをdevelopブランチにmergeして良いかレビュー&修正
- GitHub上でmerge
参照 : 『プルリクエストを使った開発プロセス』
機能ブランチの作成
チームメンバーでまだGitに関する何のセットアップもしていない方は
を参照してください。
まず、リモートの変更をローカルに反映させます。
$ git checkout develop $ git pull origin develop次に、機能ブランチを切ります(作成します)。今回はブランチ名を「add-readme」とします。できるだけ、説明的なブランチ名にすると良いでしょう。
$ git checkout -b add-readmeadd & commit
まず、機能を追加・変更・削除します。ここでは、codeディレクトリ直下に、README.mdというファイルを作ります。READMEとはプロジェクトの説明などを書く場所で、主に外部の人がこのプロジェクトがどのようなものなのか理解するために使うものです。ちなみに
.mdはマークダウン記法を表す拡張子です。ファイルを作成し、ここでは内容を以下のように書き換えます。/README.md# Django Sprint This is a tutorial for UTokyo Project Sprint.各自好きなように書いてください。
次に、変更を保存、反映させます。
$ git add -A $ git commit -m "Add README"pull request
作業を完了したら、まずpushします。
$ git push origin add-readme次に、pull request(プルリク)を送り、チームメンバーの確認段階に入ります。詳しい内容や手順は、
を参照してください。
これから
今後、細かいGit関連のコマンドは省略したいと思います。Git関連は慣れが重要なので、README.mdや次の設定変更などで一度使ってみることをおすすめします。
厄介なのは、コンフリクトを起こしたときです。まずGoogleで調べてみて、類似の事例がない場合は遠慮なくご相談ください。
各種設定
settings.py
一度settings.pyを開いてみてみましょう!
settings.pyはこのプロジェクトの「設定」を記述したものです。ここで各種設定を変更することができます。よく使うので、ざっと見ておくと良いでしょう。タイムゾーンの変更
試しにタイムゾーン(時刻帯)を変更してみましょう。まず、settings.pyから以下の記述を探し出してください!
/config/settings.py... TIME_ZONE = 'UTC' ...デフォルトではタイムゾーンは「UTC」、つまりロンドンのそれに設定されています。これを東京のものに変更するには以下のように書き換えてみれば良いです。
/config/settings.py... TIME_ZONE = 'Asia/Tokyo' ...言語の変更
続いて言語を変更してみましょう。デフォルトでは「en-us」、つまり、英語(アメリカ)に設定されています。Djangoはたくさんの言語をサポートしており、幸いにも日本語にも対応しています。日本語に変更するには以下のように書き換えれば良いです。
/config/settings.py... LANGUAGE_CODE = 'ja' ...モデル概論
MVCモデルとは
MVCモデルとは
- モデル(Model): データベースとコントローラーの間で、データ処理を行うファイル群
- ビュー(View): ブラウザとコントローラーの間で、リクエストの取得やHTMLなどのファイルの出力を担うファイル群
- コントローラー(Controller): 中枢でモデルとビューからデータを受け取り、処理して返すファイル群
詳しくは
を参照してください。
DjangoにおけるMVCモデル
かなりややこしい表記の違いがあります。
- モデル(Model): Djangoではモデル(Model)と呼ばれる
- ビュー(View): Djangoではテンプレート(Template)と呼ばれる
- コントローラー(Controller): Djangoではビュー(View)と呼ばれる
以後、ビューと書けば「コントローラー」を意味していると考えてください。
具体的なモデルファイル
具体的なモデルのファイルを見てみましょう。ここでは、サンプルとして他のプロジェクトから持ってきたものを見てみましょう。
... class Post(models.Model): author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) title = models.CharField(max_length=200) text = models.TextField() created_date = models.DateTimeField(default=timezone.now) published_date = models.DateTimeField(blank=True, null=True)ブログアプリの記事のモデルをイメージしてください。この
class PostはExcelのシートのようなものです。一方、authorやtitleなどはExcelのシートの各カラム(列)に対応します。CharFieldなどはそのデータの型を表します。もしもモデルと別のモデルを組み合わせたいときはForeignKeyなどを使います。上の例ではauthorはPostモデルとユーザーモデルを繋ぐものです。このようなフィールドの種類とオプションは以下のドキュメントを参考にしてください。ユーザーモデルと認証、管理者
Djangoにはユーザーモデルとその認証機能(ユーザー名、メールアドレス、パスワード)がデフォルトで付属しています。(パスワードはハッシュ化されて保存されます。)その点他のフレームワークよりも楽で、堅牢です。
ただし、注意しなければならないのは最初にユーザーモデルのカスタマイズを行わないと後から変更するのが難しくなる点です。不可能ではないのですが、面倒です。そこで、本チュートリアルでは最初に少しだけカスタマイズしておき、その後のカスタマイズを容易にしておきます。(実際に公式ドキュメントでも強く推奨されています。)
新しいアプリケーションの作成
まず、アプリケーションを作成します。Djangoにおけるアプリケーションとは、プロジェクトを構成する機能的な単位の一つです。再利用を簡単にするために機能ごとに分けることができます。しかし、本チュートリアルでは「cms」(Contents Management System)というアプリケーションにひとまず全てまとめようと思います。
$ docker-compose run --rm web django-admin startapp cmsこれで、次のようなディレクトリ構造になったか確認してください。
code ├─ requirements.txt ├─ README.md ├─ manage.py ├─ config │ ├─ __init__.py │ ├─ asgi.py │ ├─ settings.py │ ├─ urls.py │ └─ wsgi.py ├─ cms │ ├─ migrations │ ├─ __init__.py │ ├─ admin.py │ ├─ apps.py │ ├─ models.py │ ├─ tests.py │ └─ views.py ├─ docker-compose.yml └─ Dockerfile先ほどみたような
models.pyやviews.pyが見えていますね!実際にはこれらのファイルを書き換えることでWebを構築します。(ファイルを追加する場合もあります。)ここで忘れずにアプリケーションを追加したという事実をDjangoに伝えましょう。
/settings.py... INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'cms.apps.CmsConfig', #Added ] ...tips : プロジェクト名を「config」にしたのは、このプロジェクトファイル全体を一つのアプリケーション(Djangoのアプリケーションとは別)と見たときに、「config」ディレクトリに設定に関する情報が含まれているからです。
models.pyの変更
モデルのファイルを書き換えますが、現時点ではコピペで構わないと思います。(もう少し簡潔な方法があるかもしれませんが、動作が確認されているのでひとまずこれで...)
/cms/models.pyfrom django.contrib.auth.base_user import ( AbstractBaseUser, BaseUserManager, ) from django.contrib.auth.models import PermissionsMixin from django.contrib.auth.validators import UnicodeUsernameValidator from django.core.mail import send_mail from django.db import models from django.utils import timezone from django.utils.translation import gettext_lazy as _ # User-related class UserManager(BaseUserManager): use_in_migrations = True def _create_user(self, email, password, **extra_fields): """ Create and save a user with the given email and password. """ if not email: raise ValueError('Users must have an email address') user = self.model( email=self.normalize_email(email), **extra_fields, ) user.set_password(password) user.save(using=self._db) return user def create_user(self, email=None, password=None, **extra_fields): extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) return self._create_user(email, password, **extra_fields) def create_superuser(self, email=None, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self._create_user(email, password, **extra_fields) class AbstractUser(AbstractBaseUser, PermissionsMixin): username_validator = UnicodeUsernameValidator() username = models.CharField( _('username'), max_length=150, unique=True, help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) first_name = models.CharField(_('first name'), max_length=150, blank=True) last_name = models.CharField(_('last name'), max_length=150, blank=True) email = models.EmailField(_('email address'), unique=True) is_staff = models.BooleanField( _('staff status'), default=False, help_text=_('Designates whether the user can log into this admin site.'), ) is_active = models.BooleanField( _('active'), default=True, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.' ), ) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) objects = UserManager() EMAIL_FIELD = 'email' USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] class Meta: verbose_name = _('user') verbose_name_plural = _('users') abstract = True def __str__(self): return self.email def clean(self): super().clean() self.email = self.__class__.objects.normalize_email(self.email) def email_user(self, subject, message, from_email=None, **kwargs): """Send an email to this user.""" send_mail(subject, message, from_email, [self.email], **kwargs) class User(AbstractUser): class Meta(AbstractUser.Meta): swappable = "AUTH_USER_MODEL"(筆写追記)もしかしたら既存のAbstractUserを継承したUserを作れば済むかもしれません
実際にはこれが裏で記述されています。それを上書きしたような形です。具体的には、
username: ユーザー名first_name: 名last_name: 姓date_joined: 参加した日時is_staff: 管理者権限を持つか?is_active: 有効なアカウントか?のカラムが設定されました。
最後に、「これをユーザーモデルとする」ことをDjangoに伝えます。settings.pyの最後の部分に
/settings.py... # Custom AUTH_USER_MODEL = 'cms.User'を付け足せば完了です。これ以降任意のタイミングでマイグレーションして大丈夫です。
admin.py
Djangoには管理者用ページが予め用意されています。これのおかげで、実際にコンソールをいじったり、SQL文を書くことなく、データを追加したり、更新したり、削除したりできます。
とりあえず、admin.pyを以下のように書き換えて、ユーザーモデルの変更を反映させましょう。
/cms/admin.pyfrom django import forms from django.contrib import admin from django.contrib.auth.models import Group from django.contrib.auth.admin import UserAdmin as BaseUserAdmin from django.contrib.auth.forms import ReadOnlyPasswordHashField from .models import ( User, ) class UserCreationForm(forms.ModelForm): """A form for creating new users. Includes all the required fields, plus a repeated password.""" password1 = forms.CharField(label='Password', widget=forms.PasswordInput) password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput) class Meta: model = User fields = ('email',) def clean_password2(self): # Check that the two password entries match password1 = self.cleaned_data.get("password1") password2 = self.cleaned_data.get("password2") if password1 and password2 and password1 != password2: raise forms.ValidationError("Passwords don't match") return password2 def save(self, commit=True): # Save the provided password in hashed format user = super().save(commit=False) user.set_password(self.cleaned_data["password1"]) if commit: user.save() return user class UserChangeForm(forms.ModelForm): """A form for updating users. Includes all the fields on the user, but replaces the password field with admin's password hash display field. """ password = ReadOnlyPasswordHashField() class Meta: model = User fields = ('email', 'password', 'is_active', 'is_staff',) def clean_password(self): # Regardless of what the user provides, return the initial value. # This is done here, rather than on the field, because the # field does not have access to the initial value return self.initial["password"] class UserAdmin(BaseUserAdmin): # The forms to add and change user instances form = UserChangeForm add_form = UserCreationForm # The fields to be used in displaying the User model. # These override the definitions on the base UserAdmin # that reference specific fields on auth.User. list_display = ('email', 'is_staff') list_filter = ('is_staff',) fieldsets = ( (None, {'fields': ('email', 'password')}), ('Personal info', {'fields': ('username', 'last_name', 'first_name')}), ('Permissions', {'fields': ('is_staff',)}), ) # add_fieldsets is not a standard ModelAdmin attribute. UserAdmin # overrides get_fieldsets to use this attribute when creating a user. add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('email', 'username', 'password1', 'password2'), }), ) search_fields = ('email',) ordering = ('email',) filter_horizontal = () # Now register the new UserAdmin... admin.site.register(User, UserAdmin) # ... and, since we're not using Django's built-in permissions, # unregister the Group model from admin. admin.site.unregister(Group)管理者は次のコマンドで生成できます。
$ docker-compose run --rm web python manage.py createsuperuserその後にユーザー名、メールアドレス(架空で良い)、パスワードを要求されるので、指示通りに設定します。(これは後から使うので忘れないでください。)
マイグレーション
最後のステップはモデルが書き換わったことをデータベースに伝えることです。これをマイグレーションと良い、Djangoでは通常
- マイグレーションファイルの作成
- マイグレーションファイルの反映
の2ステップからなります。
$ docker-compose run --rm web python manage.py makemigrations $ docker-compose run --rm web python manage.py migrateこれで、初期設定は完了です!
管理者画面
http://localhost:8000/admin/ にアクセスすると、管理者のログイン画面になると思います。そこで、先ほど設定した「ユーザー名」と「パスワード」を入力すると、このような画面になるはずです。
さて、このユーザー「追加」をクリックすると、簡単にユーザーが追加できます。一度、サンプルユーザーを追加してみましょう。
参照
- Django Sprint #0 イントロダクション
- Django Sprint #1 環境構築
- Django Sprint #2 新規プロジェクトのスタート
- Django Sprint #3 ユーザーモデルのカスタマイズ
- Django Sprint #4 トップページの作成
- Django Sprint #5 汎用ビューとCRUD 前編
- Django Sprint #6 汎用ビューとCRUD 後編
- Django Sprint Appendix Docker関連
- Django Sprint Appendix 各種実装まとめ
- Django Sprint Appendix モデルとデータベース
- Django+PostgreSQLのアプリケーションをAWSのElastic Beanstalkにデプロイする (UTokyo Project Sprint 用)
- Django+MySQLのアプリケーションをAWSのElastic Beanstalkにデプロイする (UTokyo Project Sprint 用)
- 投稿日:2020-04-30T16:44:58+09:00
application.propertiesの設定を環境変数を用いてlocal起動とDocker起動で切り替える
はじめに
下記の記事からの補足になる
【IntelliJ + Docker (APP+DB) + SpringBoot (Maven) 環境構築】
https://qiita.com/SSM3G/items/bd61970648d94ccb691adocker-compose.ymlに環境変数を記載
environmentでDockerコンテナを起動する際に渡す環境変数を記述できる
docker-compose.ymlversion: '3' services: app: image: openjdk:14-jdk-alpine ports: - "80:8080" volumes: - .:/app working_dir: /app command: ./mvnw spring-boot:run environment: DATASOURCE: jdbc:mysql://db:3306/sample db: # 省略application.propertiesに環境変数を記載
下記部分
spring.datasource.url=${DATASOURCE:jdbc:mysql://localhost:3306/sample}application.propertiesspring.datasource.url=${DATASOURCE:jdbc:mysql://localhost:3306/sample} spring.datasource.username=root spring.datasource.password=password spring.datasource.driver-class-name=com.mysql.jdbc.Driver
${環境変数:デフォルト値}と記載
環境変数が設定されている場合は環境変数を読み込む
設定されていない場合はデフォルト値を読み込むSpringBoot起動
ローカル起動
環境変数は何も設定していないため
デフォルト値のjdbc:mysql://localhost:3306/sampleを読み込むDocker起動
docker-compose.ymlでDATASOURCEという名で環境変数を設定しているため
appのコンテナ内ではこの環境変数が適応される1.コンテナ内でSpringBootを起動
2.コンテナ内のapplication.propertiesを読み込む
3.環境変数のjdbc:mysql://db:3306/sampleを読み込む
setで環境変数を確認したところ、ちゃんと設定されていましたおわり
${環境変数:デフォルト値}の書き方が全然わからなくてハゲそうだった
SprinBoot application.properties 環境変数 切り替え 変数 リテラル ${} シェル変数 とかで色々調べちまった
- 投稿日:2020-04-30T15:13:35+09:00
条件絞って Docker Image を削除する
grep と awk を組み合わせてやるぞ。
docker images | grep condition | awk '{print $3}' | xargs docker rmi
- 投稿日:2020-04-30T13:42:47+09:00
Comics reader ( onigoetz/comicsreader )
zip書庫対応
起動
docker run \ --name=comics \ --restart unless-stopped \ -it -d \ -v $(pwd):/comics \ -p 8080:8080 \ onigoetz/comicsreader
- http://localhost:8080 にアクセスして表示されること
認証 (nginx)
htpasswduser-name:{PLAIN}pass-w@rddefault.confserver { listen 80; server_name localhost; location / { auth_basic "Restricted"; auth_basic_user_file /etc/nginx/htpasswd; proxy_pass http://192.168.xx.xx:8080; } }docker run -it --restart=always -d \ --name nginx \ -v $(pwd)/nginx/default.conf:/etc/nginx/conf.d/default.conf \ -v $(pwd)/nginx/htpasswd:/etc/nginx/htpasswd \ -p 80:8080 \ nginx
- http://localhost にアクセスして表示されること
- 投稿日:2020-04-30T13:35:29+09:00
macOS で Docker 内で動かした X11 アプリを表示させる
手順としては以下のような感じになります。
前準備
X11サーバ(XQuarts)をセットアップ。
brew cask install xquartzとかで XQuarts を入れておくdefaults write org.macosforge.xquartz.X11 enable_iglx -bool trueでOpenGLも使えるようにする- XQuarts を起動して「環境設定→ セキュリティ→ ネットワーク・クライアントからの接続を許可する」をチェック
- XQuarts を起動して「環境設定→ 入力→ OptionキーでAlt_LとAlt_Rを送信」をチェック(※X11アプリの実行自体には必須ではないがAltキーを使いたいので)
以上で準備OK。今後は XQuarts を起動さえしてあれば X11 が使えます。
上記2を XQuarts の起動後に実行していた場合は一度 XQuarts を再起動しといたほうが良いかも。あとは人によりますが、今後もX11アプリケーションをよく使うようなら XQuarts を自動起動しておくなど。
Docker で X11 アプリを実行してみる
実行時は
DISPLAY環境変数にホスト名を設定し、~/.XauthorityをボリュームマウントしてやればOKです。docker run --rm -e DISPLAY="$(hostname):0" -v ~/.Xauthority:/root/.Xauthority alpine sh -c 'apk add --no-cache xeyes && xeyes'とか、OpenGL を使ったデモなら↓こんな感じでとりあえず動きます。
docker run --rm -e DISPLAY="$(hostname):0" -v ~/.Xauthority:/root/.Xauthority alpine sh -c 'apk add --no-cache mesa-demos && glxgears'注意点
自分がハマった点なのですが、XQuarts を初めて起動する以前に
docker run -v ~/.Xauthority:/root/.Xauthority 〜を実行したことがあると、
~/.Xauthorityというパスに空ディレクトリが作成されてしまい、その後のX11アプリケーションの実行に支障が出ます。もし以下のような状態になってしまっているようなら
$ ls -ld ~/.Xauthority* drwxr-xr-x 2 kawaz staff 64 2020-04-30 13:11:11.716 /Users/kawaz/.Xauthority -rw------- 1 kawaz staff 49 2020-04-30 13:16:24.357 /Users/kawaz/.Xauthority-n
rm -rf ~/.Xauthority*してから XQuarts の再起動をしましょう。意図してその状態にしているなら
docker runの引数を-v ~/.Xauthority-n:/root/.Xauthorityに変えてやれば動きます。まぁ意図している人には釈迦に説法ですが、意図してない人が大抵だろうから通常は一度削除しとく対処で良いと思います。参考
基本的には参考エントリと同じこと書いてますが
~/.Xauthorityの辺りでハマったので個人的整理も兼ねてこのエントリを書きました。
- 投稿日:2020-04-30T11:47:27+09:00
【SPAチュートリアル】Django (Django REST Framework) + Nuxt.js (Vuetify) で作る実践レベルのWebアプリケーション - 4. バックエンド(Django)の基礎 -
※本記事は【SPAチュートリアル】Django (Django REST Framework) + Nuxt.js (Vuetify) で作る実践レベルのWebアプリケーションの第四章です。
本チュートリアルを実践すれば、簡単なアプリケーションをフルスクラッチで開発できるようになります。
この記事は第四章の"バックエンド(Django)の基礎"です。
技術的な指摘、わかりにくい点など、何でも気軽にコメントください最初に
本章は3部構成といたします。
- 第一部
本記事はここです。
- Djangoの基本構成
- Django REST Framework
- 第二部
- 設定ファイルとロギング
- 第三部
- ユーザ管理と認証
- 権限管理
本記事の内容を実践するのに必要な時間は、2時間です。
本章のスクリプトは、下記のGithubリポジトリのchapter-6というブランチにアップしております。Djangoの基本構成
習うより慣れろという言葉があります。
プログラミングにおいても非常に重要な考え方でしょう。不慣れな人もまずは書いてみる。そこから始めましょう。
git branch chapter-6でブランチを切り替えてから、作業を開始することを忘れないようにしてください。
masterで始めてしまうと、後から泣きます。また、Djangoの基礎と題していますが、事細かに説明は記述しません。
わからないところは公式サイトを参考にしてください。Djangoの基本構成
アプリケーション作成
Djangoでは、プロジェクトの配下に複数のアプリケーションを配置するという構成になります。
早速、作ってみましょう。今回はタスク管理アプリケーションなので、
tasksという名称にしましょう。$ python manage.py startapp tasks # 下記の構成でファイルが自動生成されます。 tasks │ admin.py │ apps.py │ models.py │ tests.py │ views.py │ __init__.py │ └─migrations __init__.py次に、追加したアプリケーションをDjangoに認識させる必要があります。
backend/backend/settings.pyというファイルにDjangoの設定を記述できるので、こちらに設定を追加します。settings.pyINSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'tasks', # <- 追加します。 ]MTVモデル
DjangoはMTVモデルを基本としています。
また、データベースの操作はSQLではなく、ORMを使用して行います。MTVについて取り扱った記事は多く見受けられるのですが、あまりしっくりくるものがなかったので独自に書きます。
- M: Model
オブジェクト指向プログラミングをご存知でしょうか?
すごく雑に言うと、実体をもつモノや、出来事を、オブジェクトとして取り扱い、オブジェクト同士の関連をもとにアプリケーションを構築していくという手法です。Modelとは、このオブジェクト指向でいうところのオブジェクトに相当する概念です。
また、ModelはORMによって、データベースのテーブル定義としても使用されます。
完全にひとつのModelがひとつのテーブルと合致するというわけではありませんので、ご注意ください。Modelの内容からデータベース定義を作成するコマンドが、
python manage.py makemigrationsです。
そして、出来上がった定義をデータベースに反映するコマンドが、python manage.py migrateです。
- T: Template
DjangoのTemplateは、雛形をもとに動的にHTMLを生成する機能です。
雛形の中には、Python変数と置き換えることを前提としたプレースホルダーを記述したり、分岐処理や繰り返し処理のような簡単なプログラムを記述することもできます。
使用するテンプレートファイルを指定して、パラメータとしてdict型変数を渡すと、プレースホルダーとPython変数が置き換わり、動的にHTMLが生成されます。Webというものは通常、ユーザからのHTTPリクエストを受けて、それに応じたHTTPレスポンスを返却します。
Djangoで開発するWebアプリケーションも、この仕組みを基本としています。静的サイトにおいては、毎回決まったHTMLデータを返却するだけでよいので、単純にHTMLファイルを配置しておけばよいのですが、Webアプリケーションのような動的サイトでは、ユーザのHTTPリクエストの内容に応じて、HTTPレスポンスを動的に作り替える必要があります。
- V: View
Webアプリケーションとしての根幹を担っています。
前項のTemplateで述べた、ユーザからのHTTPリクエストを受けて、それに応じたHTTPレスポンスを返却する機能です。
Viewはリクエストの内容をもとに、データベースの操作(CRUD)などを実行し、最後にHTTPレスポンスを返却します。
このHTTPレスポンスの返却のときに、必要に応じて前項のTemplateを使用することができます。以下、少し話の本筋とはそれますが..
Viewの説明で、Templateを呼び出すものとして取り扱っている記事を見ることがあります。
Viewの本質はあくまでもHTTPリクエストをもとに処理を実行して、HTTPレスポンスを返却することにあり、Templateはいわばオマケ的要素でしかありません。
なお、本チュートリアルで開発するアプリケーションではHTMLではなくJSONを返却するので、Templateは使いません。Django REST Framework
REST APIという言葉をご存知でしょうか?
REST APIとは、Web APIの設計思想です。
Web APIを作成するときは、こういう理念のもとに設計すべきというルールです。
REST APIとはあくまでも思想であり、こういう場合はこうしないといけない、という絶対的な正解がないため、深みにハマりすぎると抜け出せなくなります(※個人的感想)。以下の記事にシンプルにまとめられているので、ご参考ください。
それでは、DjangoでREST APIを実装していきます。
Djangoには、Django REST FrameworkというREST APIの実装を助けてくれる強力なパッケージがあります。インストール
それでは、導入していきましょう。
公式サイトのインストール手順に則っていきます。
まずはpipコマンドでパッケージを開発環境にインストールします。$ pip install djangorestframeworkDjangoにDjango REST Frameworkを認識させます。
settings.pyINSTALLED_APPS = [ ... 'rest_framework', # <-- 追記します ]Django REST Frameworkでは、Webブラウザ上で簡単にAPIを実行して試せるbrowsable APIという機能があります。
基本的に、APIを実行できるのはログインしているユーザだけになります。
browsable APIでもログインを必要とするので、ログイン機能が必要です。
ログインするためのViewとTemplateはDjango REST Frameworkがデフォルトでサポートしてくれているものを使用します。Djangoのルーティングは下記のように作成していきます。
なお、ルーティングというのはURLとView関数を対応させることで、ルーターはルーティングをまとめる箱のことをいいます。
- アプリケーションごとにルーターを作成
- 各アプリケーションのルーターの中身=ルーティングを、プロジェクト全体のルーターに放り込む
backend/urls.py"""backend URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/3.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin from django.urls import path, include, re_path # <-- include, re_pathを追加 urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^api-auth/', include('rest_framework.urls')), # <-- ルーターを統合 ]'rest_framework.urls'というのは、rest_frameworkアプリケーション内にあるurlsという名前空間から、ルーティングをimportしてくることを指します。
もう少し直接的な表現をすると、urls.pyというファイルを探します。
そして、Djangoのルーティングの暗黙のルールとして、urls.pyの中にあるurlpatternsという配列型の変数をimportします。
from restframework.urls import urlpatternsみたいな感じですね。
実際に自分でurls.pyを作成していくと、感覚がつかめると思います。では、
python manage.py runserverを実施して、http://localhost:8000へアクセスしてみましょう。URLが存在しませんというエラーが表示されました。
このアプリケーションでは、admin/と^api-auth/(正規表現で^ついてます)しかルーティングされてないから、/にアクセスされても困るよって言われています。
これまでは、ルーティングを全くしていない状態だったため、実は本エラーページの代わりにDjangoのデフォルトページにリダイレクトされていたんですね。まだ開発始めてないよね?ようこそDjangoへ!的な流れです。
http://localhost:8000/api-auth/へアクセスしてみましょう。またエラーページになりましたね。
実は、api-auth/にはルーティングは設定されておらず、api-auth/login/,api-auth/logout/(正規表現は省略)にのみ、ルーティングが設定されております。[name='login']は、このルーティングに対して、識別するための名前が設定されていることを表します。
http://localhost:8000/api-auth/login/にアクセスします。今度こそログイン画面が表示されるはずです。ところでまだユーザが存在していないため、ログインできません。
一度Ctrl + cでサーバを停止して、コマンドからユーザを作成しましょう。$ python manage.py createsuperuser # エラーメッセージが表示されて... ... django.db.utils.OperationalError: no such table: auth_userアプリケーション内で作成された定義をデータベースに反映していないため、エラーが表示されます。
Django内でデフォルトで用意されているアプリケーションがあり、そのアプリケーションが必要とするテーブルが存在しないため、エラーとなっております。
migrateコマンドでデータベースを更新しましょう。$ python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK Applying auth.0001_initial... OK Applying admin.0001_initial... OK Applying admin.0002_logentry_remove_auto_add... OK Applying admin.0003_logentry_add_action_flag_choices... OK Applying contenttypes.0002_remove_content_type_name... OK Applying auth.0002_alter_permission_name_max_length... OK Applying auth.0003_alter_user_email_max_length... OK Applying auth.0004_alter_user_username_opts... OK Applying auth.0005_alter_user_last_login_null... OK Applying auth.0006_require_contenttypes_0002... OK Applying auth.0007_alter_validators_add_error_messages... OK Applying auth.0008_alter_user_username_max_length... OK Applying auth.0009_alter_user_last_name_max_length... OK Applying auth.0010_alter_group_name_max_length... OK Applying auth.0011_update_proxy_permissions... OK Applying sessions.0001_initial... OKもう一度、
createsuperuserを実行してログインしましょう。$ python manage.py createsuperuser # Usernameとか聞かれるので適当に回答してください。ログインには成功しているはずですが、ログイン成功時にリダイレクトする
/accounts/profile/というURLが存在せず404エラーとなります。
ログインに成功すると、普通は何かしらのトップページへ遷移しますよね。その遷移先URLがデフォルトで/accounts/profile/となっています。
ただ、このURLに対してルーティングを設定していないので、404エラーが発生します。
このリダイレクト先URLは設定で任意のものに変更できます。一旦、ここまででインストール自体は完了とします。
自作APIを作ってみる
それでは、実際にAPIを作っていきましょう。
tasksアプリケーション内に実装していきます。<タスク>というリソースに対してアクセスするAPIを作っていきましょう。
/tasks/task/というURIで、<タスク>リソースにアクセスできるようにします。
URI メソッド 操作 /tasks/ GET タスクの一覧を取得する /tasks/ POST タスクを新規作成する /tasks/<id>/ GET 指定したタスクを取得する /tasks/<id>/ PUT 指定したタスクの内容をすべて更新する /tasks/<id>/ PATH 指定したタスクの内容を一部更新する /tasks/<id>/ DELETE 指定したタスクを削除する 以下の手順で開発していきます。
- models.py (リソースを作成)
- serializers.py (JSON <-> Modelオブジェクト変換機能)
- views.py (URIへのアクセス時の処理を定義)
- urls.py (ルーティング)
- models.py
タスクリソースを定義します。
現段階ではタスクとしての最低限の情報しか持たしていません。models.pyfrom django.db import models class Task(models.Model): class TaskStatus(models.IntegerChoices): ADDED = 10 DOING = 20 PENDING = 30 DONE = 100 title = models.CharField('Title', max_length=50) detail = models.TextField('Detail', max_length=500, null=True, blank=True) deadline = models.DateField('Deadline', null=True, blank=True) status = models.IntegerField('Status', choices=TaskStatus.choices, default=TaskStatus.ADDED) def __str__(self): return self.title上記のモデル定義をデータベースへと反映させましょう。
# migrate関連のコマンドは、アプリケーション単位でも実行できます。 $ python manage.py makemigrations tasks $ python manage.py migrate tasks
- serializers.py
このファイルは
startappコマンドで自動生成されていないので、手動で作成してください。
なお、Serializerというのはどういうものか、簡単に触れておきます。
Djangoでは、ModelオブジェクトまたはQuerysetオブジェクトをORMを使用して操作します。
従来は、このModel(Queryset)オブジェクトをTemplateに渡してHTMLを動的生成して、HTTPレスポンスとして返却するというのが主な流れだったのですが、最近ではHTMLではなくJSONでデータの中身だけを返却することが増えました。
そこで、Model(Queryset)オブジェクトの中身を抜き出してJSONに変換(Serialize)するために、Serializerというものが開発されました1。
このSerializerには、JSONからModel(Queryset)オブジェクトへ変換する、Desirializeという機能も含まれています。
HTTPリクエストをJSONで受け取り、DeserializeしてModel(Queryset)オブジェクトに変換、ORMで操作することができます。当然、Serializerを作成しようと思うと、Serialize, Deserializeの設定を作成しないといけないのですが、Django REST Frameworkでは、モデル定義をもとにSerializerを自動生成することができます。
serializers.pyfrom rest_framework import serializers from tasks.models import Task class TaskSerializer(serializers.ModelSerializer): class Meta: model = Task fields = ( "id", "title", "detail", "deadline", "status", )
ModelSerializerというクラスを継承して、Meta情報としてモデルおよび使用するフィールドを指定すると、Serializerができあがります。
このModelSerializerには、save()メソッドなど、Modelオブジェクトを操作するためのメソッドが既に用意されています。
つまり、Modelオブジェクトに変換してからORMで保存する、という処理が既に実装済みということです。
- views.py
URIにアクセスした際の処理を実装していきます。
views.pyfrom rest_framework.viewsets import ModelViewSet from tasks.models import Task from tasks.serializers import TaskSerializer class TaskViewSet(ModelViewSet): queryset = Task.objects.all() serializer_class = TaskSerializerSerializerのときと同様に、
ModelViewSetというクラスを継承して、いくつか追加情報を設定すると、Viewができあがります。
querysetというのは、このViewで取り扱う対象を、Querysetオブジェクトで指定しています。
serializer_classは、このViewで使用するSerializerを指定しています。先ほど作成したTaskSerializerを指定します。Djangoには関数ViewとクラスベースViewという2種類が存在します。
基本的には、クラスベースViewを使用します。詳しくは以下の記事によくまとまっております。
参考記事: Djangoのクラスベースビューのas_viewて何なの?
- urls.py
このファイルは
startappコマンドで自動生成されていないので、手動で作成してください。urls.pyfrom rest_framework import routers from tasks.views import TaskViewSet router = routers.SimpleRouter() router.register('', TaskViewSet) urlpatterns = router.urlsルーターに対して、ViewSetクラスを対応付けます。
内部的にどういうことが起こるかは、公式サイトを参考にしてください。
簡単にいうと、暗黙のルールに則って、URIとView関数が紐づけられます。できあがったルーターを、アプリケーション全体のルーターに統合しましょう。
backend/urls.pyurlpatterns = [ path('admin/', admin.site.urls), re_path(r'^api-auth/', include('rest_framework.urls')), re_path(r'^tasks/', include('tasks.urls')), # <-- この行を追加してください。 ]
さあ、これでAPIが実装できました!
http://localhost:8000/tasks/へアクセスしてみましょう。データを入力して、POSTボタンを押してみましょう。
登録もできましたね
![]()
http://localhost:8000/tasks/<id>/へアクセスすると、特定のタスクのデータのみを取得できることや、更新、削除ができることも確認してみてください。
※ PATCHメソッドを試したいときは、HTML Formではなく、Raw Dataから入力してください。最後に
ちょっと長くなってきたので、ここで一回終了とします。
第四章後半では、設定ファイルの書き方、ロギングの使い方
- 投稿日:2020-04-30T10:34:40+09:00
#docker sync start ( unison ) がエラーで動かない ( MacOS Catallina 10.15.3 )( Error getting mapped port, exit code 0 )
解決
gem uninstall docker-sync gem install docker-sync docker-sync clean ( rm ~/.docker-sync-global.yml ) docker-sync starthttps://github.com/EugenMayer/docker-sync/issues/540#issuecomment-372992379
Error
$ docker-sync start $ docker-sync start ok Stopping sync container foo-bar-app ok Starting unison for sync foo-bar-app ok foo-bar-app container not running ok starting foo-bar-app container command docker start foo-bar-app && docker exec foo-bar-app supervisorctl restart unison ok starting initial sync of foo-bar-app command docker inspect --format='' foo-bar-app command docker inspect --format='' foo-bar-app error Error getting mapped port, exit code 0 message Template parsing error: template: :1:3: executing "" at <index (index .NetworkSettings.Ports "5000/tcp") 0>: error calling index: index of untyped nil command unison -testserver /app_sync "socket://127.0.0.1:"Original by Github issue
- 投稿日:2020-04-30T03:39:36+09:00
【自分用】4/30進捗
やったこと(後ほど追記します)
awsにdockerでデプロイ
EC2のElasticIPとインスタンスの作成・紐付け(ssh通信設定)参考url
https://qiita.com/hagyyyy/items/959c115e0a5001972604
https://qiita.com/Atsushi_/items/f10a6790972528682d25
- 投稿日:2020-04-30T01:02:30+09:00
docker-compose 備忘録
- 投稿日:2020-04-30T00:17:23+09:00
BargeのDockerを最新化し、docker-composeを導入する
結論
Docker最新化の方法
$ sudo /etc/init.d/docker restart latestdocker-composeをインストールする方法
$ sudo wget "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -O /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-composeBargeとは
Dockerホストに特化したLinuxディストリビューションです。
Dockerで軽量OSというとAlpine Linuxが思い浮かびますが、用途が全く異なります。BargeはDockerホスト向けで、Alpine LinuxはDockerイメージ向けです。
詳しい説明は公式や、分かりやすい記事に譲り、自分が使ってみた感想だけ書きます。
良いところ
- 軽量で起動が高速
最新のBarge2.13.0のisoイメージのサイズは 驚異の14MB 。
UbuntuやCentOSのイメージファイルと比較すると、その軽量ぶりが際立ちます。
OS isoイメージファイルサイズ CentOS 7.8 4.5GB Ubuntu 20.04 2.5GB Barge 2.13.0 14MB
- 最初からDockerがインストールされている
UbuntuやCentOSにはDockerがデフォルトで入っておらず、またOSのバージョンによってはインストール手順が複雑です。動作確認の前にインストールで躓いたことがある人も多いのではないでしょうか(経験談)。
Bargeには最初からDockerが入っているため、起動すればすぐにDockerを使えます。また、Dockerのバージョンの切り替えも簡単なので、特定のバージョンをサクッと使いたいというニーズにも応えられます。微妙なところ
パッケージ管理が独特
Ubuntuでいうところのapt、CentOSでいうところのyumは、Bargeではpkgというコマンドです。
FreeBSDのパッケージ管理コマンドもpkgという名前ですが、特に関係ないようです。
他のディストリビューションでは難なく入れられる(またはデフォルトで入っている)パッケージが、簡単にインストールできないことがあります。(例:curl)最近更新されていない
2020年4月時点で、最新のリリースバージョンは2.14.0-rc2で、リリース日は2019年8月です。
それまでは少なくとも2月に1度以上はリリースされていたため、今後更新されない可能性もあります。環境
Vagrant boxを利用して起動
[bargee@barge ~]$ cat /etc/os-release NAME="Barge" VERSION=2.13.0 ID=barge ID_LIKE=busybox VERSION_ID=2.13.0 PRETTY_NAME="Barge 2.13.0" HOME_URL="https://github.com/bargees/barge-os" BUG_REPORT_URL="https://github.com/bargees/barge-os/issues"Dockerの最新化
Barge のデフォルトのDockerは古いです。CE版になる以前のもので、2016年頃のバージョンです。
[bargee@barge ~]$ docker --version Docker version 1.10.3, build 20f81ddアップデートが必要なので、以下のコマンドを打ちます。
ここで、/etc/init.d/は省略不可能です。通常のdockerコマンドとは異なることに注意してください。(通常のdockerコマンドがどこを指しているかは、which dockerで確認できます。)[bargee@barge ~]$ sudo /etc/init.d/docker restart latest docker[647]: Loading /etc/default/docker WARNING: Possible Forward-Incompatibility of libnetwork Once you upgrade Docker to v1.12 or newer, if you downgrade back, you may need to initialize /var/lib/docker/network/files/local-kv.db. Downloading v19.03.8 ...少し時間がかかるので気長に待ちましょう。
Dockerデーモンの再起動が終わったら、バージョンが更新されていることを確認します。[bargee@barge ~]$ docker --version Docker version 19.03.8, build afacb8b7f0
latestとすると最新版のDockerに切り替わりますが、以下のように特定のバージョンを指定することもできます。[bargee@barge ~]$ sudo /etc/init.d/docker restart v19.03.8docker-composeのインストール
Barge には
docker-composeはデフォルトで入っていません。公式サイトの手順 通りにインストールしようとすると、curlが無くて詰みます。sudo pkg install curlとしてもcurlはインストールできませんでした。
代わりにwgetがデフォルトで入っているため、wgetで代用します。2020年4月時点でのdocker-compose安定版の最新バージョン(1.25.5)をインストールします。[bargee@barge ~]$ sudo wget "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -O /usr/local/bin/docker-compose [bargee@barge ~]$ sudo chmod +x /usr/local/bin/docker-composecurlのファイル保存先指定は
-o
wgetのファイル保存先指定は-O
curl -Oとwget -oにはそれぞれ別の意味があって... ややこしいですね。
Bargeはusr/local/binにデフォルトではPATHが通っていないので、PATHが通っている/usr/binにシンボリックリンクを設定します。
バージョンを確認して、PATHを通せたことを確認します。[bargee@barge ~]$ sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose [bargee@barge ~]$ docker-compose --version docker-compose version 1.25.5, build 8a1c60f6以上で、Barge に最新のDockerとdocker-composeをインストールできました。
参考
- 投稿日:2020-04-30T00:05:53+09:00
docker-composeでアプリサーバーコンテナからMySQLサーバーコンテナに接続する。
実行環境
Docker for Mac
Docker version 19.03.8簡単な事だけどかなり手こずったのでまとめ。
Dockerfile
FROM ruby:2.7.1-buster RUN gem install rails # node.jsをインストール RUN apt-get update && \ apt-get install -y node.js # yarnをインストール RUN apt-get update && apt-get install -y curl apt-transport-https wget && \ curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \ echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ apt-get update && apt-get install -y yarn RUN rails webpacker:install RUN yarn install --check-files COPY Gemfile /Gemfile COPY Gemfile.lock /Gemfile.lock RUN bundle install *開発環境には node.js、 yarn、 webpackerのインストールが必要なので先にインストールしておく。docker-compose.yml
version: "3" services: mysql: image: mysql:8.0.20 command: --default-authentication-plugin=mysql_native_password environment: MYSQL_ROOT_PASSWORD: root app: build: . volumes: - ".:/app" ports: - "3000:3000" tty: true depends_on: - mysql working_dir: "/app"これらを元にdocker-composeでコンテナを立ち上げていきます。
$ docker-compose up立ち上がったらコンテナ内にアクセス。
$ docker exec -it (立ち上げたコンテナのNAMES) /bin/bashmariadb-clientをインストール
$ apt install mariadb-clientmysqlにアクセス
$ mysql -u root -proot -h mysql * docker-compose.yml参照 -u = ユーザーを指定 -p = 指定したユーザーのパスワード -h = ホスト、mysqlコンテナの名前?MySQL [(none)]> *アクセス成功一度ログアウトしconfig/database.ymlを編集します。
具体的にはdatabaseがsqliteになっていたのでmysql2に変更します。# SQLite. Versions 3.8.0 and up are supported. # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile # gem 'sqlite3' # default: &default adapter: mysql2 encording: utf8 username: root password: root host: mysql pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: <<: *default database: rails_development # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: <<: *default database: rails_test production: <<: *default database: rails_productionGemfileもsqliteからmysqlに変更
source 'https://rubygems.org' git_source(:github) { |repo| "https://github.com/#{repo}.git" } ruby '2.7.1' gem 'rails', '~> 6.0.2', '>= 6.0.2.2' # sqliteからmysql2へ gem 'mysql2' gem 'puma', '~> 4.1' gem 'sass-rails', '>= 6' gem 'webpacker', '~> 4.0' gem 'turbolinks', '~> 5' gem 'jbuilder', '~> 2.7' ~省略~$ rake db:create $ mysql -u root -proot -h mysql * もう一度mysqlに接続 $ show databases; * rake db:createが出来ているか確認MySQL [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | rails_development | | rails_test | | sys | +--------------------+ 6 rows in set (0.011 sec)一応ここまでやっとけば開発できると思う。完全に自分用で参考にならないかもしれません。
参考: Docker超入門 Part03 - 複数コンテナを動作させる

















