20201017のdockerに関する記事は12件です。

oxidizedとgitlabでネットワーク機器のコンフィグ管理自動化検証

はじめに

oxidizedとgitlabでネットワーク機器のコンフィグ管理を自動化する検証の個人メモ。
ネットワーク機器をたくさん運用している現場に役立つかも。

今回の検証では、VagrantでvSRX、dockerでoxidizedとgitlabを立ち上げます。
vSRXのコンフィグをoxidizedで自動取得し、gitlabに保存することが目的です。

設定変更作業後にコンフィグを手動で取得して、そのファイルをUSBで社内NWに移して、共有フォルダに格納して構成管理する、、という無駄作業が少しでも減ればうれしいところ。

最新のコンフィグが適切と管理されていないと、故障等で機器交換するとき大変なので、ちゃんと自動化します。

環境

  • mac OS Catalina 10.15.7
  • docker 19.03.13
  • docker-compose 1.27.4
  • vagrant 2.2.10

目次

  1. docker準備
  2. vSRX準備
  3. gitlab準備
  4. oxidized準備
  5. 実行

docker準備

docker周りの準備をします

dockerインストール

この記事を参考にdockerとdocker-composeをインストール

以下自分の環境

# docker -v
Docker version 19.03.13, build 4484c46d9d
$ docker-compose -v
docker-compose version 1.27.4, build 40524192

dockerが利用できるメモリ上限を引き上げる

Mac版dockerはデフォルトでメモリが2GBまでしか使えないので、この記事を参考にいい感じに増やしておく。メモリ4G/スワップ1Gくらい?マシンスペックと相談。

これを怠ると、後でgitlabに502エラーを一生突きつけられて心折れます。
gitlabがやたらメモリ使うので注意!

vSRX準備

今回は、ネットワーク機器を模擬するのにVagrant+vSRXを使います。

vagrantとvirtual boxをインストール

この記事を参考にvagrantとvirtual boxをインストール

以下自分の環境

$ vagrant -v
Vagrant 2.2.10

vagrantのプラグインをインストール

vSRXを動かすのにプラグインが必要?なので無心で入れていきます。

$ vagrant plugin install vagrant-host-shell
$ vagrant plugin install vagrant-junos

以下自分の環境

$ vagrant plugin list
vagrant-host-shell (0.0.4, global)
vagrant-junos (0.2.1, global)

vSRX立ち上げ

太古のvSRXをvagrant上で起動します。packetmode(ルータ)のvSRXを使ってください。
間違えてflowmode(FireWall)のvSRXを使うと、pingで一生複製(DUP)されて返ってきて気が狂います。

# ディレクトリ作成
$ mkdir vSRX

# ディレクトリに移動
$ cd vSRX

# vSRXのVagrantfileを作る
$ vagrant init juniper/ffp-12.1X47-D15.4-packetmode

# vSRXのIPを適当に設定。今回は192.168.33.10
$ sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile

# vSRXを起動 気長に待つ 結構時間かかる
$ vagrant up

# ステータス確認 runningになっていればOK
$ vagrant status
Current machine states:

default                   running (virtualbox)

The VM is running. To stop this VM, you can run `vagrant halt` to
shut it down forcefully, or you can run `vagrant suspend` to simply
suspend the virtual machine. In either case, to restart it again,
simply run `vagrant up`.

vSRXユーザ作成

後で使うので、oxidized用にユーザを作ります。
前の項目と同じディレクトリで作業。
ユーザとパスワードは後で使います。

# vSRXにsshログイン
$ vagrant ssh
--- JUNOS 12.1X47-D15.4 built 2014-11-12 02:13:59 UTC
root@vsrx%

# vSRX cliモードに移行
root@vsrx% cli
root@vsrx> 

# vSRX configureモードに移行
root@vsrx> configure
root@vsrx#

# oxidizedのユーザを追加
root@vsrx# set system login user oxidized class super-user
root@vsrx# set system login user oxidized authentication plain-text-password
New password:[好きなパスワード入れてエンター]
Retype new password:[もう一回入れてエンター]

# 設定をcommitする
root@vsrx# commit

# exitを数回やってvSRXから抜ける
# ssh oxidized@192.168.33.10 とかでsshできるのを確認するのもあり
# ssh時、WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!がでたらknow_hostsから192.168.33.10を消してみる

gitlab準備

dockerでgitlabを立てていきます。

docker-compose.yaml作成

gitlabのdocker-composeファイルを作ります。

# ディレクトリ作成
$ mkdir gitlab

# ディレクトリに移動
$ cd gitlab

# docker-compose.yamlファイル作成
$ touch docker-compose.yaml

docker-compose.yamlを以下に編集します。

gitlab/docker-compose.yaml
version: '3.8'
services:
  gitLab:
    image: gitlab/gitlab-ce:latest
    ports:
     - "10080:80"
    volumes:
     - './config:/etc/gitlab'
     - './logs:/var/log/gitlab'
     - './data:/var/opt/gitlab'

gitlab実行

docker-compose upで実行していく

$ docker-compose up -d

docker-compose up自体は早いですが、
プラウザで見れるようになるまで、気長に待ちます。結構時間かかります。
立ち上げが完了するまでは、woops!とか502とかエラーが表示されて悲しい気持ちになります。待ちましょう。

gitlabアクセス

http://localhost:10080 にブラウザアクセス

fig1.png

画面に従って、rootのパスワードを初期設定してください。

gitlab oxidizedユーザ作成

oxidizedが使うユーザを作ります。

http://localhost:10080 にブラウザアクセス

fig2.png

oxidizedのユーザを作成して、画面通り進んでいきます。

gitlab リポジトリ作成

oxidizedで使うプライベートリポジトリを作ります。今回は以下の名前で。
Project name: config-auto-collector

fig3.png

リポジトリの作成が完了しました。

fig4.png

oxidized準備

oxidized周りの準備をします

docker-compose.yaml作成

oxidizedのdocker-composeファイルを作ります。

# ディレクトリ作成
$ mkdir oxidized

# oxidized/に移動
$ cd oxidized

# docker-compose.yamlファイル作成
$ touch docker-compose.yaml

docker-compose.yamlを以下に編集します。
extra_hostsの存在知らなくて2日寝込みました
dockerコンテナにhostsを自動設定してくれるので、便利

oxidized/docker-compose.yaml
oxidized:
  restart: always
  image: oxidized/oxidized:latest
  ports:
    - 8888:8888/tcp
  environment:
    CONFIG_RELOAD_INTERVAL: 600
  volumes:
    - ./oxidized:/root/.config/oxidized
  extra_hosts:
    - vSRX:192.168.33.10

oxidizedの設定(config)

oxidizedのconfig設定をしていきます。

# もいっこディレクトリ作成
$ mkdir oxidized

# oxidized/oxidized/に移動
$ cd oxidized

# configファイル作成
$ touch config

configを以下に編集します。
不要な設定がある気もしますが、信じてコピペします。
一部IPやパスワードは自分の環境のものを入れてください。
取得間隔(interval)が10秒になっているので、本番環境に入れるときは要チューニング。
(半日、1日位毎くらいでもいいかも)

oxidized/coxidized/config
---
username: oxidized
password: oxidized
model: junos
resolve_dns: true
interval: 10
use_syslog: false
log: "/root/.config/oxidized/logs/oxidized.log"
debug: false
threads: 30
timeout: 20
retries: 3
prompt: !ruby/regexp /^([\w.@-]+[#>]\s?)$/
rest: 127.0.0.1:8888
next_adds_job: false
vars: {}
groups: {}
models: {}
pid: "/root/.config/oxidized/pid"
crash:
  directory: "/root/.config/oxidized/crashes"
  hostnames: false
stats:
  history_size: 10
input:
  default: ssh, telnet
  debug: false
  ssh:
    secure: false
  ftp:
    passive: true
  utf8_encoded: true
output:
  default: git
  git:
      user: oxidized
      email: [gitlabでoxidizedアカを作るときに指定したメールアドレス]
      single_repo: true
      repo: "/root/.config/oxidized/config-auto-collector"
hooks:
  push_to_remote:
    type: githubrepo
    events: [post_store]
    remote_repo: "http://[ローカルホストの実IP]:10080/oxidized/config-auto-collector.git"
    username: oxidized
    password: [gitlabのパスワード]
source:
  default: csv
  csv:
    file: "/root/.config/oxidized/router.db"
    delimiter: !ruby/regexp /:/
    map:
      name: 0
      model: 1
      username: 2
      password: 3
    vars_map:
      enable: 4
model_map:
  cisco: ios
  juniper: junos

oxidizedの設定(router.db)

oxidizedのrouter.db設定をしていきます。
oxidizedで取得対象となるネットワーク機器を設定する感じです。


# oxidized/oxidized/配下で作業
# router.dbファイル作成
$ touch router.db

router.dbを以下に編集します。

oxidized/coxidized/router.db
vSRX:juniper:oxidized:[vSRXのoxidizedユーザのパスワード]

リポジトリ準備

せっかく作ったリポジトリをcloneしておきましょう。
localhostなどは使わずに、必ず実IPでアクセスしてください。
このリポジトリは、dockerコンテナと共有されるファイルですので、
localhostにしておくとdockerコンテナ側から簡単にアクセスできなくなります。(たぶん)

# oxidized/oxidized/配下で作業
$ git clone http://oxidized@[ローカルホストの実IP]:10080/oxidized/config-auto-collector.git

実行

やっとoxidized実行。
gitlab、vSRXが立ち上がっている状態で実行します。

oxidized起動

# oxidized/配下で作業
$ docker-compose up -d

うまくいくと勝手にリポジトリにvSRXのコンフィグが入ってきます。
もちろん、vSRXのconfigを変更すると、自動でリポジトリにpushされます。
めでたしめでたし。

fig5.png

後は細かなチューニングやホスト登録とかして、本番環境にデプロイしましょう。

Tips

vagrantが固まったとき

ps -ef|grep VBoxで出てきたpidをkillしましょう。
vSRXがよく固まる印象

dockerコンテナに入る

『docker 入る』と2万回くらいググりました。覚えましょう

$ docker-compose exec [container名] bash

TODO

  • ファイル名がホスト名になっちゃうのどうにかしたい
  • 出力されるconfigファイルに、実行コマンドが表示されないのなんとかしたい
  • 自作modelで取得情報を拡張させたい(show int terseとか)
  • 実環境で試す
  • ホストの扱いいい方法ないもんかなあ、、対象ホストが多くなると、手打ち辛い

感想

  • oxidizedはドキュメント少なくて辛い
  • インターネットにでれる環境であれば、わざわざローカルにgitlab立てなくてOK
  • 一回デプロイしてしまえばあとは楽ちん運用できそう
  • cvsのUIがダサいので、gitlabを使ってみたけど、単純にコンフィグファイルの世代管理だけならcvsのほうが見やすい気がする
  • gitlabの機能を持て余している感ある。なんか面白いことできないかなあ
  • gitlabリソース使いすぎ、仮想環境じゃないほうがいいのかも
  • gitはそもそもネットワーク運用メンバーに馴染みがないから、あんま使わないほうが良いかも
  • vSRX、plain-text-passwordでユーザ作ってもコンフィグみるとencryptedになっているんだがなんでじゃ?そういうもの?

おわり

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

BinaryBuilder.jlがすごい〜自動でDockerでクロスコンパイルしてcやFortranのコードをJuliaライブラリ化

Juliaを使っていると、時々Arpack_jllみたいな、jllと名のついたパッケージを見たことはありませんか?
大抵、何らかのパッケージをインストールする時に依存関係としてjllのついたパッケージが入っていると思います。
実は、このjllとついたパッケージ、Julia言語ではない他の言語で書かれたコードがコンパイルされたものなのです。インストールする時にはOSに合わせて自動でバイナリがダウンロードされます。

これを実現するのは、
BinaryBuilder.jl
https://github.com/JuliaPackaging/BinaryBuilder.jl
というパッケージです。

私は
https://www.youtube.com/watch?v=3IyXsBwqll8
これを見て存在を知りました。

どうやら、Dockerを使うことで、Mac、Windows、Linuxの様々なプラットフォームでのクロスコンパイルを行ってコードをコンパイルしているようです。その際、それぞれのOSごとに上手く行かない場合には適宜コンパイル方法を修正したりするようです。

非常に面白そうなライブラリですので、試してみました。

今回入れてみたのは、C-LIMEです。
https://usqcd-software.github.io/c-lime/
格子QCD(格子量子色力学)のためのデータフォーマットです。私は全然詳しくありませんが、規模がちょうど良かったので試してみました。

環境

Julia 1.5.2
Mac OS 10.15

BinaryBuilder.jlのインストール

まず、Dockerが必要ですので、Dockerを入れておきます。Dockerのインストール方法は適当に調べてください。
Macであれば、

$ brew install docker
$ brew cask install docker

でいけそうです。

その後、Juliaで]を押してパッケージモードにして、

add BinaryBuilder

とします。しかし、2020年10月17日現在、GitHubの何かが変わったために現状のバージョンでは動かないため、上の代わりに

add BinaryBuilder#f126fe7

として修正されたバージョンを入れる必要があります。

使い方

入れた後は、

using BinaryBuilder
BinaryBuilder.run_wizard()

とwizardを実行します。

Make a platform selection
 > All Supported Platforms
   Select by Operating System
   Fully Custom Platform Choice

ではAll Supported Platformsを選び、

Please enter a URL (git repository or compressed archive) containing the source code to build:

ではコンパイルしたいソフトウェアのgithubアドレスかファイルを指定します。ここでは、

https://github.com/usqcd-software/c-lime.git

としました。
あとは指示に従っていきます。最初の問いはgitのブランチのどれを選ぶかですが、これはmasterとしておきます。
今回のコードは特に追加のソースコードやライブラリは必要ありません。
進んでいくと、
名前をつけるのとか、バージョンをつけるのとかありますので適当に入れていきます。

進んでいくと

sandbox:${WORKSPACE}/srcdir

みたいなものが出てきます。ここで、コードのコンパイルを行います。
今回の場合なら、

cd c-lime/
./autogen.sh 
./configure --prefix=${prefix} --build=${MACHTYPE} --host=${target}
make 
make install

でコードをコンパイルできます。そして、Ctrl+Dでlogoutします。
次に

Your build script was:

    cd $WORKSPACE/srcdir
    cd c-lime/
    ./autogen.sh 
    ./configure --prefix=${prefix} --build=${MACHTYPE} --host=${target}
    make
    make install

Would you like to edit this script now? [y/N]: n

とコンパイル方法がまとめられているので、特に問題がなければnとします。
そのあと、何をコンパイルするの?みたいなものが出てくるので、aを押してdを押します。
あとはenterを推しつつ色々なOSやプラットフォームでのコンパイルを行います。

さて、出来上がったあとは、

How should we deploy this build recipe?
 > Prepare a pull request against the community buildtree, Yggdrasil
   Write to a local file
   Print to stdout

と聞かれます。
もし最初を選ぶと、GitHubのYggdrasil(ユグドラシル)というところにpull requestをします。
これは、どのようにコンパイルすればいいか、という情報をここに載せることを意味します。

Would you like to actually open the pull request or just prepare it?
 > Go ahead, open it
   No, just prepare it and let me look at it first

そのあと、自分のgithubのアカウント名でpull requestをすることになります。

もし無事に終了すれば、pull requestが自動で行われます。
そして、問題がなければYggdrasilにマージされます。
マージされると、
https://github.com/JuliaBinaryWrappers/
に登録されます。
ここに登録されれば完了です。
https://github.com/JuliaBinaryWrappers/CLIME_jll.jl
は既に登録されたものですが、

Linux aarch64 {libc=glibc} (aarch64-linux-gnu)
Linux aarch64 {libc=musl} (aarch64-linux-musl)
Linux armv7l {call_abi=eabihf, libc=glibc} (armv7l-linux-gnueabihf)
Linux armv7l {call_abi=eabihf, libc=musl} (armv7l-linux-musleabihf)
Linux i686 {libc=glibc} (i686-linux-gnu)
Linux i686 {libc=musl} (i686-linux-musl)
Windows i686 (i686-w64-mingw32)
Linux powerpc64le {libc=glibc} (powerpc64le-linux-gnu)
macOS x86_64 (x86_64-apple-darwin)
Linux x86_64 {libc=glibc} (x86_64-linux-gnu)
Linux x86_64 {libc=musl} (x86_64-linux-musl)
FreeBSD x86_64 (x86_64-unknown-freebsd)
Windows x86_64 (x86_64-w64-mingw32)

というプラットフォームであればバイナリを提供できるとあります。

Juliaのライブラリとしての使い方

以後は

add CLIME_jll

とするとインストールできます。
今回のCLIMEはライブラリではなく実行するタイプですので、
https://juliapackaging.github.io/BinaryBuilder.jl/dev/jll/
を参考にすると、

using CLIME_jll
lime_contents() do exe
    run(`$exe`)
end

とすることで、実行ファイルlime_contentsをJulia上で実行することができます。
なお、今回のコードは実際は引数が必要ですので、run(`$exe lime_file_test`)みたいな形で使います。

今回はBinaryBuilder.jlをMac上で実行しましたが、それだけで様々なプラットフォームに対応したJuliaライブラリができてしまいました。驚きです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Raspbian(buster)にdockerとdocker-composeをインストールする

新しく購入したラズパイにdockerとdocker-composeの環境を構築したので、備忘録として残します。

実行環境

Raspberry Pi 4
メモリ : 4GB
OS : Raspbian GNU/Linux 10 (buster)

dockerのインストール

既存の環境のdockerを削除

真っ新な環境なので、ないと思いますが念のため

sudo apt remove -y docker docker-engine docker.io containerd runc

パッケージの更新

? sudo apt update

dockerのインストール

以下のコマンドでrootユーザーになって、インストール用スクリプトを取得して実行

? su -
? curl https://get.docker.com | sh

実行後、以下のコマンドで入っていることを確認

? docker -v
Docker version 19.03.13, build 4484c46

rootユーザー以外でも利用できるようにする

現状では、一般ユーザーはdockerを使えません。

? grep docker /etc/group
docker:x:995:

なので、以下のコマンドで利用できるユーザーを設定します。
今回はreishisuというユーザー名を追加してみました。

? usermod -aG docker reishisu

そして、もう一度確認するとreishisuというユーザーが追加されていることがわかります。

? grep docker /etc/group
docker:x:995:reishisu

docker-composeのインストール

公式サイトでは、以下のように書かれており64bitでのインストール方法しかありませんでした...?

公式ページより引用
- You can run Compose on macOS, Windows, and 64-bit Linux.

ですが、直接GitHubからリポジトリをcloneして実行すればインストールできます。

リポジトリをcloneしてくる

? su -
? git clone https://github.com/docker/compose.git

最新のバージョンにチェックアウト

2020/10/17現在だと "1.27.4" です。

? cd compose
? git checkout -b 1.27.4

ビルドする

めちゃくちゃ時間がかかりますが、気長に待ちましょう(自分の環境だと15分くらいかかりました)

? ./script/build/linux

バイナリをコピーしてコマンドを実行できるようにする

ビルドが完了するとdistという名前のディレクトリが作成されているので、移動してバージョンを確認してみます。

? cd dist
? ./docker-compose-Linux-armv7l version
docker-compose version 1.28.0dev, build a24843e1
docker-py version: 4.3.1
CPython version: 3.7.7
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019

なので、docker-composeというコマンドとしてどこからでも実行できるように、binフォルダにコピーします。

? cp docker-compose-Linux-armv7l /usr/local/bin/docker-compose

コピーが完了すると、どこからでもdocker-composeコマンドが使えるようになってます。

? cd
? docker-compose version
docker-compose version 1.28.0dev, build a24843e1
docker-py version: 4.3.1
CPython version: 3.7.7
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019

一般ユーザーでも実行できるようにする

パーミッションを755に変更して、rootユーザー以外も読み取りと実行をできるようにします。

? chmod 755 /usr/local/bin/docker-compose

こんな感じになってたらOKです!!

? ll /usr/local/bin
合計 7.8M
-rwxr-xr-x 1 root root 7.8M 10月 17 21:34 docker-compose

これでdockerとdocker-composeのインストールは完了です。

お疲れ様でした!!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Docker】引数を指定してコマンドラインツールとして使う(wrapper script)

はじめに

今回、自分の作成したプログラムを提供して使ってもらうのに、

  • 毎回 docker run して使う
  • 引数を docker run のコマンドラインで指定する

という形でプログラムの整備をしました。そのメモを書きます。これは昨今の流れに従うもので、このようにして提供されているオープンソースで使われる一般の使い方のようです。

自作のプログラムで

$ prog <arg1> <args2>

と整備したものを、そのままdocker image に整備して

$ docker run -t prog_image <arg1> <arg2>

として利用できるようになります。

次を参考にしてできました。

上記の情報で十分だと思いますが、あえてハマりポイントを挙げると、、、

  • CMDでなくENTRYPOINTで:これまでDockerfile で CMD で実行内容を指定していましたが、これだど引数を受け付けないようです。ETNRYPOINT にしたら動きました。
  • 実行権限: image 内部での権限が問題のように見えた時、RUN chmod +x を Dockerfile に書いたら動いた。(それでの良いのか^^;)

動作確認

構成

実現方法は、docker build で

  • 実行プログラムprogをインストールする
  • prog を実行するためのためのスクリプトを用意する(wrapper script を呼ぶらしい)
  • wrapper script を dockerfile の ENTRYPOINT に設定する

です。(直接実行プログラムを指定しても良さそうな気がしますが、シェルを通したほうがいろいろ良いことがあるのでしょうか。そこのところは分かりませんが。)

動作例

テスト用に作ってみました。

  • 実行プログラム。hello.c コマンドラインの引数を表示するプログラム。
hello.c
#include <stdio.h>
#include <stdlib.h>

int main(const int argc, const char**argv)
{
    for(int i=0; i< argc; i++){
        printf("argv[%d]=%s\n", i, argv[i]);
    }
    return EXIT_SUCCESS;
}
  • wrapper script: ただ引数を渡す
docker_entrypoint.sh
#!/bin/bash
echo "I am a wrapper script."
hello $@
  • Dockerfile: ビルドしてインストールし、wrapper script をentrypoint に指定する
FROM ubuntu:18.04

RUN apt-get update -y && \
  apt-get install -y -qq --no-install-recommends \
  build-essential \
  gcc

COPY hello.c /tmp/
RUN  cd /tmp && gcc /tmp/hello.c -o hello && mv hello /usr/local/bin/
COPY docker_entrypoint.sh /usr/local/bin

ENTRYPOINT ["docker_entrypoint.sh"]
  • いざ動かしてみる
> docker build -t test .
...
Successfully tagged test:latest

> docker run --rm -t test Dear my friends.
I am wrapper script.
argv[0]=hello
argv[1]=Dear
argv[2]=my
argv[3]=friends.

スクリプトなくても動作

今の場合、Dockerfile の ENTRYPOINT に直接実行プログラムを指定しても動きました。

ENTRYPOINT [ "hello" ]

まとめ

  • とりあえず、Linux で動く環境をそのままdocker run で動かすプログラムにする方法は分かった

今後の課題。

  • docker run の管理は、通常のcontainer の管理と同じだと思うが、要確認。CPUなどのリソースの指定や使用状況の取得、HEATHCHECK など気になる。
  • Wrapper を使う理由の理解を深める。複数のプログラムを組み合わせて逐次実行する指定をできたりするところかな。

今日(正確には昨日)も生き延びることができた。
(2020/10/17)

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerコンテナ内でのgdbエラー対応

概要

Dockerコンテナ内でgdbコマンドを使ってCプログラムのデバッグをしようとしたところ,以下のような
warning: Error disabling address space randomization: Operation not permitted
と怒られました.

(gdb) b 5
Breakpoint 1 at 0x117c: file test.c, line 5.
(gdb) r
Starting program: /home/user/dev/test 
warning: Error disabling address space randomization: Operation not permitted

予想がつくとは思いますが雑にいうと,gdbはシステムコールを利用しているが,コンテナの中からは権限が無いためホストマシンのデバイスにアクセスできないらしい.

解決策

システムコールを許可してあげるオプションを付与してあげる.

  • docker run実行時
$ docker run -it --cap-add=SYS_PTRACE --security-opt="seccomp=unconfined" [CONTAINER_NAME] /bin/bash
  • docker-composeでの場合

service下に以下を書いてあげる.

docker-compose.yaml
    cap_add: 
      - "SYS_PTRACE"
    security_opt: 
      - "seccomp=unconfined"

参考記事

https://sott0n.github.io/posts/docker_gdb/

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

OpenJDKのDockerコンテナを使ってKotlinアプリのビルドを行う

経緯

  • KotlinでAndroid開発をやっているが、毎度AndroidStudioでビルドするのが面倒になってきた
  • gitlabを使ってるのでついでにgitlabciを使ってみよう(別プロジェクトでrunner設定済みだったので今回必要なさそう)
  • まずは手動でコンテナからビルドできるか試してみよう

Dockerインストール

最近手に入れた開発用Macなので、まだDockerが入っていませんでしたorz
ここは特に書くことないので省略します

コンテナ起動まで

今回はopenjdk8を使用します
理由はgitlabciのAndroid用テンプレートYAMLにデフォルトとして使われているのがこいつだったのと、JAVAのパッケージとかをインストールする手間が省けるからです(だから使われてるんだと思うけど)

まずはいつも通りpullします
バージョン指定は必須です

docker pull openjdk:8-jdk

そしてコンテナ起動します

docker run -it openjdk:8-jdk

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

上記まで行うと自動的にコンテナの中に入れると思うので、パッケージをインストールしていきます

apt-get --quiet update --yes
apt-get --quiet install --yes wget tar unzip lib32stdc++6 lib32z1

export ANDROID_COMPILE_SDK=28
export ANDROID_BUILD_TOOLS=29.0.3
export ANDROID_SDK_TOOLS=6514223
export ANDROID_HOME="/android-home"

install -d $ANDROID_HOME
wget --output-document=$ANDROID_HOME/cmdline-tools.zip https://dl.google.com/android/repository/commandlinetools-linux-${ANDROID_SDK_TOOLS}_latest.zip

pushd $ANDROID_HOME
unzip -d cmdline-tools cmdline-tools.zip
popd
export PATH=$PATH:${ANDROID_HOME}/cmdline-tools/tools/bin/

sdkmanager --version

yes | sdkmanager --sdk_root=${ANDROID_HOME} --licenses || true
sdkmanager --sdk_root=${ANDROID_HOME} "platforms;android-${ANDROID_COMPILE_SDK}"
sdkmanager --sdk_root=${ANDROID_HOME} "platform-tools"
sdkmanager --sdk_root=${ANDROID_HOME} "build-tools;${ANDROID_BUILD_TOOLS}"

chmod +x ./gradlew

コンソールでエラーが出ていないかの確認と、念の為printenvで環境変数の確認くらいはやっても良いと思います

git clone

ビルドするソースコードをコンテナ内に持ってきます
ここはcloneするだけなので省略

ビルド実行

ビルド自体は簡単で、Gradleのコマンドを叩くだけです

./gradlew assemble

variantsとflavorを使いたい人はコマンドを変更してください
こちらを参考にさせていただきました

ただ、このままだとエラーになってうまく行かないです
私はここで躓いてしまったので、そのポイントを2点紹介いたします

local.properties作成

ビルドした際に下記のエラーが発生しました

「SDK location not found. Define location with an ANDROID_SDK_ROOT environment variable or by setting the sdk.dir path in your project's local properties file at」

「local propertiesにSDKの場所が書かれてない」的なエラーに見えます

言われたとおりlocal propertiesを探したのですが見つかりませんでした

AndroidStudioをのときは勝手に作られてた(多分)ので意識してなかったのですが、どうやらlocal propertiesを作り、SDKの場所を記載しないといけないようです

そもそもvimを入れてなかったのでそこからです^^;

apt-get install vim

アプリのトップフォルダに移動して

vi local.properties

中身はこんな感じです

## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Wed Jan 07 15:34:05 JST 2015
sdk.dir=/android-home

これで再度ビルドコマンドを叩きましたが、今度は別のエラーが

メモリ上限解放

次のエラーは
「Could not connect to kotlin daemon. Using fallback strategy.」
という内容

調べてみると、メモリが上限まで行ってデーモンちゃんが死んじゃったみたいです

Macのステータスバーにあるクジラのマークをクリックして、dockerのアプリから設定を変更して上限メモリを増やしてあげます
やり方の詳細はこちらを参考にさせていただきました

ビルド成功!!

ようやく「BUILD SUCCESSFUL」の文字が!

ビルドの際に署名を聞かれなかったことが気になってるので、そこに関しては後日追記したいと思います
Debugだからかなーと思いましたが、AndroidStudioでビルドするときはReleaseでもDebugでも署名必要なのでなんとも言えませんね

今回はdockerfileを作りませんでした
理由はgitlabci.yamlに記載するからです

次回は

  • gitlabciからcommit時に自動ビルド
  • variantsとflavorを指定してビルド

あたりができたらなと思います

以上です
お付き合いいただきありがとうございました

※全体的にこちらも参考にさせていただきました

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

docker image を使って Apache Kafka を実行してみるまで

1. はじめに

Apache Kafka は スケーラビリティに優れる分散メッセージキューです。
メッセージキューとは、システム間のデータの受け渡しを仲介し、データを一時的に保持(キューイング)するミドルウェアのことです。

今回は、Apache kafka の Docker Image を使用し、ローカル環境で kafka を実行していきます。
使用する Apache kafka のバージョンは、2.6.0 です。

2. 参考(実行環境)

 2-1. docker がインストールされている
$ docker -v
Docker version 19.03.6, build 369ce74a3c
 2-2. スペック

メモリはトータルで8GB搭載されているマシンを使用しましたが、4GB程度でも問題なく動作します。

$ cat /etc/issue
Ubuntu 18.04.2 LTS
$ cat /proc/meminfo | grep Mem
MemTotal:        8168284 kB
MemFree:         5540948 kB
MemAvailable:    7472660 kB

3. コンテナのビルド・開始

Docker hub に kafka の Docker image は多く公開されています。
今回はこちらで用意した Docker image を使っています。

$ docker run --name my-kafka blueskyareahm/kafka:2.6.0

以下のように、Image がダウンロードされた後、コンテナが起動します。
※この画面はそのままにしておきます(Ctrl + C すると、コンテナが停止します)

Unable to find image 'blueskyareahm/kafka:2.6.0' locally
2.6.0: Pulling from blueskyareahm/kafka
75f829a71a1c: Already exists 
455e7974a143: Pull complete 
a439c4ff44d0: Pull complete 
b9eb8968940e: Pull complete 
e6979812c85a: Pull complete 
7812677cc867: Pull complete 
ceacbc38a4c6: Pull complete 
70319b3a888f: Pull complete 
3fb4c3130215: Pull complete 
68dc00f6ba7c: Pull complete 
Digest: sha256:802f5d87bfb51fd5af66853a345e0ed65de8acc2f3fd61c259def2d6c05f63d6
Status: Downloaded newer image for blueskyareahm/kafka:2.6.0
/usr/lib/python2.7/site-packages/supervisor-4.2.1-py2.7.egg/supervisor/options.py:474: UserWarning: Supervisord is running as root and it is searching for its configuration file in default locations (including its current working directory); you probably want to specify a "-c" argument specifying an absolute path to a configuration file for improved security.
  'Supervisord is running as root and it is searching '
2020-10-17 04:52:25,057 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  If you intend to run as root, you can set user=root in the config file to avoid this message.
2020-10-17 04:52:25,068 INFO RPC interface 'supervisor' initialized
2020-10-17 04:52:25,069 CRIT Server 'unix_http_server' running without any HTTP authentication checking
2020-10-17 04:52:25,069 INFO supervisord started with pid 1
2020-10-17 04:52:26,076 INFO spawned: 'zookeeper' with pid 9
2020-10-17 04:52:26,082 INFO spawned: 'kafka' with pid 10
2020-10-17 04:52:27,091 INFO success: zookeeper entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2020-10-17 04:52:27,091 INFO success: kafka entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

4. Kafka Topic の作成

別のコンソールを開いて、以下のコマンドを実行します。
このコマンドでは、Kafka Topic を作成しています。(ここでは、名前を "topic1" としています)
Kafka は Topic を介してメッセージをやり取りします。

$ docker exec -it my-kafka /opt/kafka/bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic topic1

以下のメッセージが表示されれば、OKです。

Created topic topic1.

5. Kafka Producer の開始

以下のコマンドを実行します。
このコマンドでは、Kafka Producer を開始しています。
以下のようにインタラクティブにメッセージを受け付ける状態になります。

$ docker exec -it my-kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic topic1
>

6. Kafka Consumer の開始

別のコンソールを開いて、以下のコマンドを実行します。
このコマンドでは、Kafka Consumer を開始しています。
実行しても、何も表示されませんが、メッセージを受け付ける状態になっています。

$ docker exec -it my-kafka /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic1

7. Kafka Producer からメッセージを送信してみる

Kafka Producer 実行中のコンソールに戻り、何らかのメッセージを入力してみます。

Producer 側

$ docker exec -it my-kafka /opt/kafka/bin/kafka-console-producer.sh --broker-list localhost:9092 --topic topic1
>Hello Kafka!
>

すると、Kafka Consumer 側に入力したものと同じメッセージが表示されます。
Consumer 側

$ docker exec -it my-kafka /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic topic1
Hello Kafka!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Djangoチュートリアル(ブログアプリ作成)③ - 記事一覧表示編

前回、Djangoチュートリアル(ブログアプリ作成)② - model 作成、管理サイト準備編では管理サイトで記事を作成するところまで確認できました。

今回は、管理サイトで作成した記事の一覧を表示できるようにしていきます。

template 準備(ファイル作成)

最初に template を作成しましょう。
templates/blog 配下に post_list.html を作成します。

└── templates
    └── blog
        ├── index.html
        └── post_list.html

view の準備

ここで少し重要な説明をします。

Django ではクラスベース汎用ビュー という仕組みを使うと、簡単に model を引っ張ってきて記事を表示させたり、
テンプレートを表示させたりすることが出来、アプリ作成をグンと効率的に行うことができるようになります。
ちなみに前々回、views.py をいじったときに generic という表記がありました、これもクラスベース汎用ビューを使う準備として必要な宣言です。

view.py
from django.views.generic import TemplateView

汎用クラスビューには様々な種類があり、その中でも単純に template を表示させるためだけに使われるのが
index.html の表示に使っていた TemplateView です。
index.html の表示のために、呼び出す template を views.py の中で指定していたことになります。

view.py
class IndexView(TemplateView):
    template_name = 'blog/index.html'

また、これまではわかりやすいように genetic で宣言してから使うクラスを指定して import していましたが
generic.xxxView の形で呼び出すこともできるので views.py を少し書き換えてあげましょう。

views.py(書き換え後)
from django.views import generic

class IndexView(genetic.TemplateView):
    template_name = 'blog/index.html'

これからたくさんのクラスベース汎用ビューを呼び出すことになるので、最初の宣言をスッキリとさせました。

さて、今回は template を単純に表示させるだけでなく、データベースから記事の情報モデルも呼び出してあげる必要があります。
そのため、別の ListView というクラスベース汎用ビューを使うのですが、使い方は TemplateView のときと似ています。

最初に使うモデルを宣言し、クラスを記述し、呼び出すモデルを指定してあげるだけです。

views.py(ListViewを追加)
from django.views import generic
from .models import Post # Postモデルをimport

class IndexView(genetic.TemplateView):
    template_name = 'blog/index.html'

class PostListView(generic.ListView): # generic の ListViewクラスを継承
    model = Post # 一覧表示させたいモデルを呼び出し

model = Post という記述を入れてあげることで、記事一覧が post_list という変数でリスト型として template に渡すことができます。

ここで TemplateView を使ったときのことを思い出して「templateを指定してあげるのでは?」と考えた方は鋭いです。

もちろん指定してもよいのですが、実は generic.ListView では template のファイル名をルールに沿った形にしてあげることで、明示しなくても呼び出してくれる便利機能があります。
(ただし、明示した方が第三者にとって分かりやすいので、敢えて記述する場合もあるかと思います。)

ルールとしては「post_list.html」のように、model名を小文字にしたものと、ListViewならば"list"という文字列をアンダースコアで区切った文字列をファイル名にすることです。
(使うクラスによって異なってくるため、後ほど説明します)

これで template である post_list.html を表示させ、同時に template に記事一覧を渡すための view の準備が整いました。

template 側で記事一覧の受け取り

post_list.html に渡されたモデルを受け取るには、Django ならではの記述方法があります。

Django の template では {% %} で囲むことで Python コードを記述でき、さらに html としてブラウザに値を表示させるには {{ }} と、中括弧を重ねたもので記述します。

今回、記事一覧は post_list というリスト型で変数が template で渡されているので for ループで展開し、それぞれの記事タイトルと日付を取り出していきます。
(各カラムのデータは、変数名にドット付きでカラム名を指定する形で取り出せます)

post_list.html
<h1>記事一覧</h1>

<table class="table">
  <thead>
    <tr>
      <th>タイトル</th>
      <th>日付</th>
    </tr>
  </thead>
  <tbody>
    {% for post in post_list %}
    <tr>
      <td>{{ post.title }}</td>
      <td>{{ post.date }}</td>
    </tr>
    {% endfor %}
  </tbody>
</table>

ルーティング設定

最後に記事一覧を表示させるための URL へアクセスした時に ListView を呼び出すよう、blog/urls.py を編集します。

blog/urls.py
from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('list', views.PostListView.as_view(), name='list'), # ここを追加
]

今回のように、何かを表示させるときには View, Template, URL がそれぞれ絡むことを覚えておいてください。

記事一覧表示の確認

これで model を表示させる準備が整ったので runserver を実行して url にアクセスしましょう。
blogアプリの中の list という URL パスを先ほど設定したので、
127.0.0.1:8000/blog/list という URL で表示できます。

image.png

表は格好よくないですが、管理サイトから登録した記事が表示されていることが分かるかと思います。
※見た目は後で BootStrap を使って整えますが、まずは Django の基礎を理解するためにベースだけ作ってしまいます。

一つだけだと分かりづらいので、ついでに記事を2つぐらい、管理サイトから追加してから再度確認してみましょう。

image.png
タイトルと日付がそれぞれ取り出せていることが分かりますね。

次回は、テストを自動化するユニットテストを作成していきます。

→次回
Djangoチュートリアル(ブログアプリ作成)④ - ユニットテスト編

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Djangoチュートリアル(ブログアプリ作成)② - model 作成、管理サイト準備編

前回 はブログアプリの基礎となる部分を作成し、動作確認まで行うことができました。
今回は、実際に記事を登録するための準備をし、記事の作成を行いましょう。

記事 model の作成

ブログで記事を管理するためには model を作成します。
model はデータベースと Django の橋渡しの役割を持っており、これのおかげで我々は SQL といったデータベース構文を意識することなくデータベースにデータを登録することができます。

最初に設定する models.py では、どのようなデータを登録していくのかを定義します。
Excelの表でいうと、表の各カラムのカラム名を定義したり、各カラムに入るデータがどのようなもの(文字列や数値など)を定義するところです。

今回はブログアプリであり、記事 (Post) を修正していくので Post モデルを作成します。
タイトル、本文、日付が入ればとりあえず十分です。

blog/models.py
from django.db import models
from django.utils import timezone # django で日付を管理するためのモジュール

class Post(models.Model):
    title = models.CharField('タイトル', max_length=200)
    text = models.TextField('本文')
    date = models.DateTimeField('日付', default=timezone.now)

    def __str__(self): # Post モデルが直接呼び出された時に返す値を定義
        return self.title # 記事タイトルを返す

次に、データベースに models.py で定義した情報を反映させます。
このままデータベースに対する処理を行うわけではなく、models.py の内容を反映させるためのワンクッションとなるファイルを作成します。
ファイルの作成を自動的に Django にやってもらうことができ、次のコマンドを実行することでファイルが作成されます。

python3 manage.py makemigrations

すると /blog/migrations 配下に番号付きのファイルが作成されます。

.
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── 0001_initial.py # これが追加される
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── templates
    └── blog
        └── index.html

Django アプリ作成の中でこのファイルを直接いじることはありませんが、中身はこのようになっており、これのおかげでカラムの作成などを Django が一気にやってくれます。

0001_initial.py
# Generated by Django 3.1 on 2020-10-17 01:13

from django.db import migrations, models
import django.utils.timezone


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Post',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=200, verbose_name='タイトル')),
                ('text', models.TextField(verbose_name='本文')),
                ('date', models.DateTimeField(default=django.utils.timezone.now, verbose_name='日付')),
            ],
        ),
    ]

さて、この migration ファイルを使ってデータベースにテーブルを作成することになりますが
反映もコマンド一発で Django が勝手にやってくれます。
以下のコマンドを実行しましょう。

(blog) bash-3.2$ python3 manage.py migrate

成功すると、一発目は大量の OK 表示とともに通常のコマンドラインに戻るかと思います。

Operations to perform:
  Apply all migrations: admin, auth, blog, 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 auth.0012_alter_user_first_name_max_length... OK
  Applying blog.0001_initial... OK
  Applying sessions.0001_initial... OK

管理サイトでテーブルを確認

いきなり記事を作成していってもよいですが、まずはちゃんとテーブルを作成されているかを UI で確認すると安心かと思います。

Django では特別用意しなくても管理サイトの UI が自動で作られ、その中で作られたテーブルを確認したり、はたまた手動で作成、編集、削除なんかもできたりします。
そのための準備をここでは行っていきます。

modelを管理サイトに反映

blogディレクトリ配下に admin.py というファイルが最初から作成されていますが、ここに先程作成した model の情報を記述することで管理サイトでこねくり回すことができるようになります。

blog/admin.py
from django.contrib import admin
from .models import Post # 追加

admin.site.register(Post) # 追加

管理ユーザを作成

管理サイトを使うためには、それ相応の権限を持ったユーザ(アカウント)、つまり superuser を作成してあげる必要があります。
これも Django のコマンドでサクッと作ることができます。

python3 manage.py createsuperuser

実行するとユーザ名、メールアドレス、パスワードを聞かれるのでそれぞれ入力しましょう。
※開発環境であれば、メールアドレスは適当なものでも問題ありません。

作成が完了すると以下のような表示がコマンドライン上に出ます。

Superuser created successfully.

管理サイトにログイン

さて、それでは Django の管理サイトに実際にアクセスしてみましょう。

まずはサーバを起動します。

python3 manage.py runserver

次にブラウザのアドレスバーに管理サイトのアドレスを入力しますが、
プロジェクトの urls.py に以下の記述があったことはお気づきでしょうか。

mysite/ursl.py
urlpatterns = [
    path('blog/', include('blog.urls')),
    path('admin/', admin.site.urls), # ここ
]

この記述は最初から存在しており、デフォルトでは "127.0.0.1:8000/admin" で管理サイトにアクセスすることができます。
(通常はあまり変更することはありませんが、本番環境ではセキュリティ上、アドレスを変更しておく場合もあります)

それでは Chrome 等で 127.0.0.1:8000/admin にアクセスします。
image.png
このようにログイン画面が表示されたら成功です。
先ほど superuser を作成したときの情報を入力し、ログインを選択します。

image.png
ログインに成功すると、管理画面が表示されます。
このような管理サイトを作成するには通常のフレームワークだと結構な準備が必要になりますが、デフォルトで用意されているのが Django の用意されているのがよいところです。

また、BLOG というアプリ欄の中で Posts という model が反映されていることも分かりますね。
(Postが複数存在することになるので、Postsという表記になっていることもポイントです)

ここで 追加 ボタンから記事を手動で作成することも出来ます。

image.png

保存を選択すると、実際に記事を作成することもできます。
image.png

更には作成した記事を編集したり、削除したりすることもできます。便利ですね。
image.png

次回は、記事をアプリ上で表示(htmlとして表示)させるようにしていきます。

→次回
Djangoチュートリアル(ブログアプリ作成)③ - 記事一覧表示編

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Djangoチュートリアル(ブログアプリ作成)① - 準備、トップページ作成編

今回は Django を使って、記事を投稿できるブログアプリを作成していきます。

シリーズに分けて紹介していきますが、まずはローカルで作成した上で Docker 構成にしたり、AWS にデプロイしたり、CircleCI で自動テスト・デプロイまでをシリーズ化していきます。

Django とは?

Djangoは Python で実装できる Web アプリケーションフレームワークです。

フレームワークとは、アプリケーションを開発する際に使われる機能がまとまったソフトウェアです。
フレームワークを導入することで、効率よく Web アプリを進めることができます。

今回は Blog アプリを作っていきますが、Django を使えばデータベースを用いた、コンテンツ管理システムやWikiからソーシャルネットワーク、ニュースサイトなど、高品質なWebアプリケーションを簡単に、少ないコードで作成できます。シンプルなWebアプリケーションであれば、数分間で作れてしまう場合もあります。もちろん、機能を拡張して複雑なWebアプリケーションを作成することもできます。

また、Djangoは、Instagram など、有名な Webアプリでも使われており、Ruby でいう Ruby on Rails に相当する注目のフレームワークとなっています。

環境構築

まずは作業用のディレクトリを作成します。
ここでの名前はなんでもよいですが、とりあえず blog としておきます。

mkdir blog
cd blog

pipenv のインストール

ベースとなる環境は汚さない方が他のモジュールなどの影響を排除できるため、pipenv を使って仮想環境を構築しましょう。

pip install pipenv
# 環境によっては直接 pip を使えない場合もあるので、python3 -m pip install pipenv でインストールします

インストールできたら、作業用フォルダの中で下記のコマンドを実行します。

pipenv shell

実行後、仮想環境に入ることが出来るとディレクトリ名に従った文字列がコマンドラインの冒頭に表示されるようになります。

(blog)bash-3.2$

Django をインストール

直接 pipenv install django とでも実行して Django をインストールしてもよいですが、
後々 Docker を使うことを考えて、requirements.txt というファイルを作業用ディレクトリ直下に作成して
必要となるモジュールを記述していくことにします。

いまは Django だけが必要なので、バージョン情報とともに以下のように記載します。

requirements.txt
Django==3.1.0

※今回は Django 3.1.0 で作っていきますが Django 2.2 あたりでも問題なく動くとは思います

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

下記のコマンドを実行することで、requirements.txt に基づきモジュールをインストールします。
ここでは Django だけがインストールされるはずです。

pipenv install -r requirements.txt

Django プロジェクトの作成

blog ディレクトリ直下で実行

django-admin startproject mysite

親プロジェクト直下でのファイル構成はこのようになっているかと思います。

├── Pipfile
├── Pipfile.lock
├── mysite
│   ├── manage.py
│   └── mysite
│       ├── __init__.py
│       ├── settings.py
│       ├── urls.py
│       └── wsgi.py
└── requirements.txt

Django サーバのテスト起動

開発用サーバを起動する機能がついています。
(Ruby on Rails をやったことがある人は rails -s というと分かりやすいかと思います)

これを実行するには manage.py ファイルが置いてあるディレクトリに移動する方が便利なので、mysite/mysite ディレクトリに移動してから実行します

cd mysite
python3 manage.py runserver

正常に実行できると下記のような出力が出ます。

October 16, 2020 - 21:30:23
Django version 3.1, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

なお、この部分は migrate というデータベースへの統合処理が済んでいないために出力されるメッセージですが、いまのところ気にしないで大丈夫です。

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.

さて、これで Django の開発用サーバが起動したのでブラウザから確認します。
Chrome などのブラウザのアドレスバーに「127.0.0.1:8000」と入力して Enter を押下します。

image.png

これがすべての始まりです。この画面が出ていれば、最初のステップは完了しています!おめでとうございます。

プロジェクトの設定

さて、先ほどテストサーバへアクセスした時に英語での表記になっていましたね。
こういった設定は mysite/settings.py で設定することができ、デフォルトでは英語圏に合わせた言語表示、およびタイムゾーンになっています。

mysite/settings.py(before)
LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

これを次のように変更してあげます。

mysite/settings.py(after)
LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

もう一度テストサーバへアクセスすると、日本語表記になっていることが分かるかと思います。
(また、この画面からでは確認できませんがタイムゾーンも東京設定になっています)

image.png

Django アプリの作成

先程 start-project コマンドでプロジェクトを作成しましたが、次はアプリケーションを作っていきます。
混乱しがちですが、ベースとなるプロジェクトと個別のアプリは別物です。

公式ページではこのような説明です。

プロジェクトとアプリの違いは何でしょうか? アプリとは、ウェブログシステム、公的記録のデータベース、小規模な投票アプリなど、何かを行う Web アプリケーションです。プロジェクトは、特定のウェブサイトの構成とアプリのコレクションです。プロジェクトには複数のアプリを含めることができます。 アプリは複数のプロジェクトに存在できます。

では、blog アプリを作っていきましょう。mysite プロジェクトリ (manage.py ファイルがある場所) の直下で下記コマンドを実行します。

python3 manage.py startapp blog

現在のディレクトリ構成はこのようになっています。

.
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── blog
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

blog 配下に様々なファイルが作成されていることが分かるかと思います。

ここで、このアプリが作成されたことをプロジェクトに教えてあげる必要があります。

mysite/setting.py の中に "INSTALLED_APPS" という欄がありますので、その中で blog アプリの存在を教えてあげましょう。

mysite/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog.apps.BlogConfig', # ここを追加
]

template, view, url の設定

まずは「 template をそれぞれ変更していきます。

template は見た目を作るための部分であり、html ファイルに相当します。

mysite プロジェクト直下に templates フォルダ、その下に blogフォルダ、さらにその下に index.html を作成します。

.
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── db.sqlite3
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── templates
    └── blog
        └── index.html ←ここに作成

index.html の中身はとりあえず適当で大丈夫です。

index.html
<h1>Hello, from Django!</h1>

また、templates フォルダをどこに作ったかをプロジェクトに教えて上げる必要があります。
INSTALLED_APPS を設定したときと同様に、settings.py に下記の記述を入れます。

settings.py
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # ここを修正
        'APP_DIRS': True,

次に views.py を修正していきます。
先ほど作った template である index.html を呼び出します。

blog/views.py
from django.views.generic import TemplateView

class IndexView(TemplateView):
    template_name = 'blog/index.html'

URL の設計

次に、blog アプリ専用のルーティング設定を作成します。
ルーティング設定は「urls.py」というファイルで設定していきます。

まずはじめに説明をしますと、プロジェクト全体のルーティングを司る urls.py と、アプリ内の urls.py それぞれでルーティングを設定します。

最初に mysite 直下の urls.py から編集します。

mysite/urls.py
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('blog/', include('blog.urls')),
    path('admin/', admin.site.urls),
]

後に作成する blog アプリ用の urls を、urlpatterns 内で読み込むことになります。

では mysite 直下にのみ urls.py が作成されていますが、blog 直下にも自分で「urls.py」を作成します。
エディタでもよいですし、アプリの blog ディレクトリ内で下記コマンドを実行してもよいでしょう。

/blog
touch urls.py

blog 配下はこのようなファイル構成です。

.
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
├── urls.py
└── views.py

作成した urls.py の中身はこのように変更することで、先程 views.py で作成した関数(=index.htmlを呼び出す処理)のルーティングを設定します。

blog/urls.py
from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
]

ちなみに name='index' を設定しておくことで「blog:index」という名前を使ってこの url を逆引きで呼び出すことができるようになります。

この時点で index.html を呼び出せるかの確認を行います。

manage.py が置いてあるディレクトリで runserver を実行します。

python3 manage.py runserver

無事に通ったら、今度はブラウザで 127.0.0.1:8000/blog へアクセスします。
これは先程 mysite/urls.py で blog 付きのアドレスでアクセスされたときに、blog アプリ内に記述した内容を動作させるようにしているためです。

アクセスし、index.html の中身が表示されれば成功です。

image.png

次回は models を作成し、実際に記事を登録するための準備をします。

→続き:
Djangoチュートリアル(ブログアプリ作成)② - model 作成、管理サイト準備編

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dockerのコマンドまとめ

はじめに

Dockerは多くのIT開発企業で導入されている環境構築を楽にする技術です。
Dockerのコマンドをまとめます。

今回のDockerコマンド

  • docker login
  • docker pull
  • docker images
  • docker run
  • docker run --name
  • docker run --rm
  • docker ps -a
  • docker restart
  • docker exec -it (コンテナID)or(コンテナ名) bash
  • docker commit (コンテナID)or(コンテナ名) (新しいimage名)
  • docker tag (source) (target)
  • docker push
  • docker rmi
  • docker stop
  • docker rm
  • docker system prune

詳細

docker login

Dockerにログインするコマンド。
Dockerを使用する場合は最初に行う。

ターミナル
% docker login
Username: => Dockerに登録したユーザー名を入力
Password: => Dockerに登録したパスワードを入力

=> ユーザー名、パスワードが合っていれば、ログインする。(Login Succeededと表示される)

docker pull

Docker imageをdockerhubからホストにダウンロードするコマンド。

ターミナル
例)hello-worldというimageをダウンロードする時

% docker pull hello-world
=> hello-worldがダウンロードされる

=> ユーザー名、パスワードが合っていれば、ログインする。(Login Succeededと表示される)

docker images

ホストの中にあるdocker imageのリストを表示するコマンド。

ターミナル
例)hello-worldというimageをダウンロードした後

% docker images
=> REPOSITORY      TAG      IMAGE ID      CREATED      SIZE
   hello-world     latest   (自動作成のID)  (作成した時)   (データサイズ)

docker run

コンテナを作るコマンド。

ターミナル
例)hello-worldというimageをダウンロードした後

% docker run hello-world
=> hello-worldのコンテナが作成され、実行される。

% docker run -it ubuntu bash
=> ubuntu(OSの名前、dockerhubに存在するdocker image)のコンテナが作成され、bashというプログラムを実行させる。
(bashはshellの名前。ubuntuのデフォルトのコマンドをbashに上書きして実行している。ちなみにubuntuのデフォルトのコマンドはbashなので、今回はdocker -it run ubuntuでも同じ。)

docker run --name

名前をつけてコンテナを作るコマンド。

ターミナル
% docker run --name sample ubuntu
=> sampleという名前のコンテナがubuntuというdocker imageから作成される。

docker run --rm

コンテナを起動した後、すぐにコンテナを削除コマンド。

ターミナル
% docker run --rm hello-world
=> hello-worldというdocker imageからコンテナを作成し、実行した後、すぐにコンテナが削除される。
(一度しか使わないコンテナは残さないために、すぐに削除する。)

docker ps -a

全てのコンテナを表示するコマンド。

ターミナル
% docker ps -a
=> 全てのコンテナが表示される。

% docker ps
=> 実行中のコンテナのみされる。

docker restart

一度実行したコンテナをリスタートするコマンド。

ターミナル
% docker restart (コンテナID)or(コンテナ名)
=> コンテナIDで指定したコンテナがリスタートされる。(STATUSがUPとなる)

docker exec -it (コンテナID)or(コンテナ名) bash

リスタートしたコンテナにプログラムを実行させるコマンド。(bashの部分は適宜、実行したいプログラムに置き換える)

ターミナル
% docker exec -it (コンテナID)or(コンテナ名) bash
=> リスタートしたコンテナの中に入ることができる。(bashにより)

docker commit (コンテナID)or(コンテナ名) (新しいimage名)

更新したコンテナを新しいDocker imageとして保存するコマンド。

ターミナル
% docker commit (コンテナID)or(コンテナ名) (新しいimage名)
=> docker imageが保存され、IDが表示される。

docker tag (source) (target)

docker imageのimage名を変更するコマンド。
docker imageをdockerhubにpushする前に、ホストのimageのリポジトリ名とpush先の自身のdockerhubのリポジトリ名を同じにするために使う。(dockerhubのリポジトリはdockerhubで作成しておく必要がある)

ターミナル
% docker tag (ホストのdocker imageのリポジトリ名:タグ名) (dockerのユーザー名/リポジトリ名)
=> docker imageのリポジトリ名がdockerhubのリポジトリ名と同じになる。(タグ名は指定しなければ、latestとなる。)

docker push

docker imageを自分のリポジトリに作成するコマンド。

ターミナル
% docker push (image名)
=> dockerhubにdocker imageがpushされる。(image名はdockerのユーザー名/リポジトリ名と同じにしておく)

docker rmi

docker imageを削除するコマンド。(image名はdockerのユーザー名/リポジトリ名と同じにしておく)

ターミナル
% docker rmi (image名)or(image id)
=> 指定したdocker imageが削除される

docker stop

実行中のコンテナをストップするコマンド。(STATUSをUP→EXITEDにする)

ターミナル
% docker stop (コンテナ名)or(コンテナID)
=> 指定したコンテナがストップされる。

docker rm

コンテナを削除するコマンド。

ターミナル
% docker rm (コンテナ名)or(コンテナID)
=> 指定したコンテナが削除される

docker system prune

ストップしているコンテナ全てを一括で削除するコマンド。

ターミナル
% docker system prune
=> ストップしているコンテナが全て削除される

参考

Udemy

かめれおん講師 「米国AI開発者がゼロから教えるDocker講座」

https://www.udemy.com/share/103aTRAEAdd1pTTHoC/

有料ですが、初学者の私にも非常に理解しやすかったです。

最後に

本投稿が初学者の復習の一助となればと幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Docker Hubにpushしたらrequested access to the resource is deniedと出てしまった

はじめに

普段あまり使わないDocker Hubを久々に使おうとしたところpushした際に
denied: requested access to the resource is deniedと出てしまった。

対応

docker build --tagで指定していたユーザーIDの部分を自分のアカウントのものと同じにしることによってpush出来るようになる。

docker image tag 元のタグ名 dockerhub_userid/app:latest

これで自分はpush出来るようになりました。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む