helloworlds

not a noun, it's a verb

【Python】Djangoのsettings.pyって2回読み込まれてる!!???

今回は、Djangoのプロジェクトでちょっとハマったことがメインです。 ※ 日本語の記事なくて、結果ですが断定して言えないのでご承知下さい!

経緯

Djangoのプロジェクトでローカル環境開発をしていました。 前回少し記事にしたやつですね。

o21o21.hatenablog.jp

こちらけっこうイジっていて、DBの設定を見直していたところ、 環境毎の切り替えが必要やん!って思って調べていました。

できるだけプロジェクト構成はシンプルにしたいので、settings.py内で収めようとしました。

環境変数を使用して、環境ごとにDBの設定を変更しようと、以下のようなかんじになりました。

SET_DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxx',
        'USER': 'xxxx',
        'PASSWORD': 'pwd',
        'HOST': 'db',
        'PORT': 3306,
    },
    'staging': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'xxx',
        'USER': 'xxxx',
        'PASSWORD': 'pwd',
        'HOST': 'db',
        'PORT': 3306,
    }
}

env = os.environ.get('DJANGO_ENV', 'default')
print('Running on "{}".'.format(env))

if env in SET_DATABASES:
    DATABASES = SET_DATABASES[env]
else:
    print('ERROR: Unknown environment for database settings.')

ちょっとif文があるけど、まあこれくらいならいいかと思い、そのままdocker-compose upで立ち上げ。

するとそんなすんなりいきませんでした。

エラー

...略...

if self._databases[DEFAULT_DB_ALIAS] == {}:
KeyError: 'default'

...略...
 django.db.utils.ConnectionDoesNotExist: The connection default doesn't exist

ん、なんかdefaultがないって言われている... でもdefaultも記述してあるなあ〜と思ってログを見てみました。

そしたらなんかsettings.pyが2回読み込まれてる疑惑が浮上。

ログのなかでprintしている内容が2回実行されていたのです。

なんだろうと思いながら調べてみると、以下の質問を発見。

stackoverflow.com

結果的に...

結果的にこの質問からすると、Djangoの起動時には、プロセスが2回別々で起動され、settings.pyが読み込まれてるらしい。 (ちょっと細かいことは調べてないです。。。)

なるほど〜、ここが大きく関係していそうだな〜

ということでした。

あんまりsettings.pyにはゴチャゴチャコード書かない方が良さそうでした。。

なので、settings.pyをちょっとファイル名を変更してもう1ファイル作成し、 起動時のsettings.py自体の読込を環境ごとに変更する方法を検討しようかと思います。

以上.

【Docker】Django + REST framework + mysql with docker-compose

今回は、DjangoのREST frameworkのローカル環境に挑戦してみました。

初めてPythonフレームワークを触るので、浅はかなところもあるかと思いますがご了承下さい!

ゴールは、ブランチでこれが表示されるところまでいきます。

f:id:o21o21:20181119195642p:plain

docker-composeを使用するので、インストールしてない方はインストールしましょう。 この記事ではインストールの説明は割愛します。(「docker for mac インストール」で検索すれば出てくると思います。)

さて、さっそく取り掛かっていきます。

※ 私の環境は、macOS

作業場作成

適当に今回のプロジェクトを作成するディレクトリに移動します。

$ cd /path/to/project
or
$ mkdir project_name

任意ですが、一応README.mdを作成。

初期データ、ディレクトリ作成

今回、DB(mysql)と接続するために、初期データを置いておく必要があります。

$ mkdir mysql
$ cd mysql
$ mkdir init

上記を作成して、mysql/init/というディレクトリを作成します。 このディレクトリ配下に、.sqlをファイルを置いて置きます。

※ この.sqlファイルですが、既存の運用で使用されているDBのdumpファイルでも可能です。 ちょっと試したいというかたは、テーブルを作成するsql文などを適当に記述してもOKです。

ここまでのプロジェクト構成は以下です。

<project_name>
├── README.md
├── mysql
│   └── init
│      └── test.sql

主要なファイルを作成

次にDockerfiledocker-compose.ymlをプロジェクトディレクトリで作成します。

$ touch Dockerfile
$ touch docker-compose.yml

重要なのは、この2つのファイルの記述です。

  • Dockerfile
FROM python:3.5

ENV PYTHONUNBUFFERED 1

RUN mkdir /code

WORKDIR /code

# install Libraries
COPY requirements.txt /code/
RUN pip install -r requirements.txt

# to be consistent versions of between "Django and PyMySQL"
RUN pip install -U PyMySQL

ADD . /code/
  • docker-compose.yml
version: '3.0'
services:
  db:
    image: "mysql:latest"
    container_name: <container_name>
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_DATABASE: <db_name>
      MYSQL_ROOT_PASSWORD: <db_root_pwd>
      MYSQL_USER: <db_user>
      MYSQL_PASSWORD: <db_pwd>
    ports:
      - 3306:3306
    volumes:
      - type: bind
        # source: ./docker/db/init.sql
        source: ./mysql/init/<file_name>.sql
        target: /docker-entrypoint-initdb.d/<file_name>.sql
      - type: bind
        source: /tmp/docker/tmpdata
        target: /tmp/tmpdata
  web:
    container_name: <container_name>
    build: .
    command: python manage.py runserver 0.0.0.0:8080
    volumes:
      - .:/code
    ports:
      - 8080:8080
    environment:
      DJANGO_SECRET_KEY: $DJANGO_SECRET_KEY
      DJANGO_DEBUBG: $DJANGO_DEBUBG
    depends_on:
      - db

ほとんど公式と同じ記述です。 ただ、公式では、PostgreSqlの場合ですし、先程作成したDBの記述はありません。 シンプルに詳細を確認したい人は、一読するといいと思います!

クイックスタート・ガイド:Docker Compose と Django — Docker-docs-ja 17.06.Beta ドキュメント

Dockerfile

こちらはシンプルですね。python ^3.5をベースにpipでrequirements.txtを元にライブラリをインストールさせています。 ここで一番注目したいのは、PyMySQLアップグレードです。

私が環境構築をしている時に、何時間もつまったのがこれ。 なんてことないエラーでしたが、どうもうまくいかなかった...

知っていればなんてことないことなのですが、どうやらDjangoのversionが2.0以上になって発生するエラーのようでした。 色々ググってみると、色んなやり方で解決されているみたいでしたが、アップグレード1発で解決されるのが一番シンプルですよね!

docker-compose.yml

こちらもいたって普通の記述です。 初期データを必要とすることで、volumesの設定(特にtarget)が重要です。

docker-entrypoint-initdb.dに注目します。 これは、mysqlのイメージがコンテナの起動時に自動的に初期データを読み込んでくれる機能を使用しています。

下のbindは、初期データがなかった場合に代用できる記述です。

ここまで作成して、足りないファイルが2つあります。

requirements.txt

このプロジェクトで必要なPythonのライブラリを記述します。

Django==2.1.1
djangorestframework
django-filter
psycopg2
psycopg2-binary

.env

docker-compose.ymlで使用されている変数があると思います。($DJANGO_SECRET_KEY) これは、Djangoのプロジェクト作成時に発行されるキーなのですが、環境変数に設定しようかと思って普通に記述すると、以下のエラーが発生。 (何故環境変数に、DjangoのSECRET_KEYを設定しようと思ったかというと、毎回毎回Docker環境を作成しては削除していると、Githubでのヴァージョン管理の際に、settings.pyは管理したいけど、SECRET_KEYは別で管理したいということになりました。)

ERROR: Invalid interpolation format for "environment" option in service "web": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

どうやらエスケープしなければならない記号が入っていて、environmentに直接値を記述できませんでした。(やり方はあるが面倒くさい..w) なので、.envというファイルを作成し、これをヴァージョン管理。

え、ヴァージョン管理するの?って思うかもしれませんが、これには理由があります。 1つ目としては、他の人に同じ.envを提供できる。(= 同様な環境構築を目指す。)また、開発環境においては他の値で代用できたりしますね。 2つ目は、STGや本番では、OSの環境変数を見に行くので大丈夫ということ。ただし、これはあくまで、本番サーバーでDockerを稼働させないことになります。 まあ、とりあえずローカル環境はDockerで!みたいな人向けになってしまいますが...(でも会社とかで作業していると、新機能作成で本番はDockerじゃないけど、機能追加のためにDocker流行ってるし今回のローカル環境はDockerにしよう!って人も多いのでは?w)

それはさておき、.envには以下を記述

DJANGO_SECRET_KEY=-<今は適当な値をとりあえずいれておく>
DJANGO_DEBUBG=True

ProjectとAppを作成

コマンドを実行してプロジェクトとアプリを作成します。

プロジェクトルートにて、以下を実行。

# プロジェクトを作成
$ docker-compose run web django-admin.py startproject settings .
# アプリケーションを作成
$ docker-compose run web python manage.py startapp src

これを実行すると、プロジェクト構成は以下のようになるかと思います。

<project_name>
├── Dockerfile
├── README.md
├── db.sqlite3
├── docker-compose.yml
├── manage.py
├── mysql
│   └── init
│       └── <file_name>.sql
├── requirements.txt
├── settings
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-35.pyc
│   │   ├── settings.cpython-35.pyc
│   │   ├── urls.cpython-35.pyc
│   │   └── wsgi.cpython-35.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── src
    ├── __init__.py
    ├── admin.py
    ├── apps.py
    ├── migrations
    │   └── __init__.py
    ├── models.py
    ├── tests.py
    └── views.py

一気にファイルやらディレクトリが作成されたかと思います。 今回、プロジェクトとアプリの作成コマンドの名前をsettingsとsrcにしました。 これは任意です。ディレクトリ名としてわかりやすいものでいいと思います。

mysqlとの接続

/settings/settings.pyを編集します。

  • DBの設定
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql,
        'NAME': <db_name>,
        'USER': '<user_name>,
        'HOST': 'db',
        'PORT': 3306,
    }
}
  • PyMySqlの読込 同ファイル、任意の箇所に以下を記述
import pymysql

pymysql.install_as_MySQLdb()

また、このファイルにSECRET_KEYが記述されているかと思います。 この値を.envのDJANGO_SECRET_KEYに追記し、 settings.pyのSECRET_KEYの部分に、os.environ.get('DJANGO_SECRET_KEY')を代わりに書いて、OSの環境変数を参照するようにします。

合わせて、DEBUGもos.environ.get('DJANGO_DEBUBG')として書き換えます。

その他、プロジェクトに合わせて、LANGUAGE_CODEとTIME_ZONEも合わせます。 (体外が、jaAsia/Tokyoでしょうか。)

INSTALLED_APPSにもこちらを追記します。'rest_framework'

DBとのシンクのために、マイグレーションファイルを作成します。

models.pyに対象のテーブル(class)を記載して実行すると、src/migrations/ディレクトリが作成され、 0001_initial.pyのようなファイルが作成されます。 はじめにmodels.pyが空の状態でmigrateをしても大丈夫ですが、src/migrations/配下にはini.pyしか作成されません。

# ホストからマイグレーションファイルををDBに適用
$ docker-compose exec web python manage.py makemigrations

# Dockerコンテナの中に入ってマイグレーションファイルをDBに適用
$ python manage.py makemigrations

# ホストからmodels.pyに書いたclassを読み込んでマイグレーションファイルを作成
$ docker-compose exec web python manage.py makemigrations <app_name>

# models.pyに書いたclassを読み込んでマイグレーションファイルを作成
$ python manage.py makemigrations <app_name>

ググってみるとほとんど記事が新規でお試しテーブルみたいなかんじでmodels.pyに記述していますが、 既存のdumpファイルから作成されたDBから以下のコマンドで、models.pyに自動でclassを作成してくれます。

$ python manage.py inspectdb tabbel_name >> models.py

実行

最後に実行です。

$ docker-compose up

.
.
.
<container_name> | You have 15 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
<container_name> | Run 'python manage.py migrate' to apply them.
<container_name> | November 19, 2018 - 19:51:55
<container_name> | Django version 2.1.1, using settings 'settings.settings'
<container_name> | Starting development server at http://0.0.0.0:8080/
<container_name> | Quit the server with CONTROL-C.

このような出力されればOKでしょう。

http://localhost:8080/

ブラウザでlocalhostにアクセスし、Welcomeページが表示されていれば、あとはもう開発を開始できます!

まとめ

だいぶ駆け足で書きました。 うまくいかない場合は、もちろん公式を参照してみて下さい。

確認としては、Dockerのコンテナにはいることで解消できる場合もあります。($ docker exec -i -t コンテナ名 bash) また、Dockerのコンテナは何度削除しても大丈夫です!($ docker rm <CONTAINER ID or NAMES>)

1からのやり直しも簡単にできるのはDockerのいいところでもあるのかなと思います。 今回私は、初期データとして、5GBのdumpファイルを用いましたが(ちょっと最初のイメージコンテナ作成時時間はかかりますが、)問題なく動作しています。

後先考えると環境構築はほんとに大変... ですが、とりあえず構築させていくことが大事ですね!

以上.

【Go】簡単!使い捨て、GoのDocker開発環境を構築

以前は、macOSでのGoのプロジェクトについて考えました。

o21o21.hatenablog.jp

今回はGo (golang)のDocker開発環境を考えてみます。 拡張性を意識して、docker-composeを利用してみます。

※ ヴァージョンの関係で1発でうまくいかない場合もあります。 分かり次第更新します!(2019/02/22更新、下部記載)

想定として、なる早で環境構築し、GoのWebアプリを開発していこう!みたいなノリです。 ちなみに、Goのフレームワークとして、echoをインストールしていきます。 ゴールは、ブラウザでのHello Worldを目指します。

私の環境は、macOSです。 事前にDocker (macならDocker for macをインストールしましょう!)

さて、順をおってみていきましょう!

プロジェクトの作成

今回、Dockerなので特にホストOS(私ならmac)のGOPATHを意識する必要はありません。 (Docker上でのGOPATHは指定します。) 気になる方は、この記事の冒頭であげた過去の記事を参考にしてみて下さい。

なので、任意のディレクトリに新規プロジェクトを作成しましょう。

必要なファイルを作成

コマンド docker-compose upで起動させるために、必要な設定ファイルを新規作成します。 この記事では必要最低限の記述にします。portの指定などご自身のやりたいことに合わせて設定してみて下さい。 ※ 自分の使用しているdocker及びdocker-composeのversionにも注目!

Dockerfile

FROM golang:latest                                                                                                                                                                                    
  
WORKDIR /go/src/go-app2
COPY . .
    
# "Go" Environment variable
ENV GO111MODULE=on
    
# install Go web framework
RUN go get -u github.com/labstack/echo
   
# install "Fresh" restart tool
RUN go get github.com/pilu/fresh

CMD ["fresh"]

上からみていきます。

goのヴァージョンは最新のものを取得しにいってます。(ヴァージョン指定も勿論可能)

GO111MODULEというGOの環境変数をonに設定します。 これでモジュールを自動的に読み込むことができます。

これをDockerfileに記述しないと、docker-compose upした時に以下のWARNINGが出ました。

go get: warning: modules disabled by GO111MODULE=auto in GOPATH/src;
    ignoring go.mod;
    see 'go help modules'

GO111MODULEを記述した際に、プロジェクトディレクトリに自動的にgo.modというファイルが作成されます。 (= 今回のプロジェクトに依存したgo.modファイルが生成される。)

そして、フレームワークのechoとホットリロードをするためのFreshをgo getでインストールします。 go getを使用するということは、今回作成されるDocker上には、複数のプロジェクトを共存させる目的ではないことを覚えておいて下さい。 仮に、go getをすると、GOPATH配下にインストールされて2つ目以降のパッケージの依存関係を管理しにくくなるからです。 (goから離れていたので、間違ってたらごめんなさい...!!!!)

GO111MODULE

さきほど定義した環境変数GO111MODULEについてです。 こちらヴァージョン1.11から追加された、モジュール管理モード環境変数です。(正式リリースは、1.12かららしい)

on : モジュール対応モード off : GOPATH モード(今まで通り) auto : GOPATH以外のみモジュールモード

今までdepなどを使用していたと思いますが、これは便利! depからの乗り換えも楽みたいですね!

ちなみに、今回のDocker環境で開発中に新しいモジュールを追加すると、freshが検知し自動的にモジュールがインストールされます。 そうすると、go.modに require package/name v1.1x.2x のように追記されていることが確認できました。 また、go.sumファイルも生成されます。これは、モジュールの依存関係を示すファイルのようです。

そして最後にコマンド実行です。

ホットリロードについてですが、どういうことかというと コンパイル不要な言語ならいいのですが、一旦コンパイルしてから動作させる言語において、 よくDockerで起動させられたけど、ファイルの編集をした際にもう一度docker runとかしないといけない...ということが起こります。

かなり面倒なので、タスクランナー的なものが必要です。 厳密に今回使用するFreshはタスクランナーとは書いてないようですが、 要はファイルを監視し変更が検知されると、自動的にrestartしてくれるものです。

なので、Dockerfileでは、最後にfreshというコマンドで起動させます。

Freshについては、以下の公式を参照してみて下さい。 Fresh自体の設定ファイルも作成できるようです。

github.com

docker-compose.yml

続いてdocker-compose.ymlですが、そんなに記述がないので説明を割愛します。

   version: '3'                                                                                                                                                                                        
   services:
     app:
       build: .
       container_name: <projecrt_name>
       volumes:
         - ./:/go/src/<project_name>
       ports:
         - "8080:8080"
      environment:
          GO111MODULE: "on"

ここまで作成できれば、ほぼ完成です。 Dockerfileを基に、1つのコンテナと1つのイメージが作成されるはずです。(golangのイメージ含めるなら2つかな?)

あとは適当にmain.goを作成します。

goファイル

  • main.go
package main

import (
    "log"
    "net/http"
    "path/filepath"
    "sync"
    "text/template"
)

type templateHandler struct {
    once     sync.Once
    filename string
    templ    *template.Template
}

func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    t.once.Do(func() {
        t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
    })
    t.templ.Execute(w, nil)
}

func main() {
    http.Handle("/", &templateHandler{filename: "top.html"})

    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal("ListenAndServe", err)
    }
}
  • templates/top.html
<p>Hellooooooooooooooooo World!!!!!!!!!!!!!!</p>

実行

いざ実行です!

$ docker-compose up
Building app
Step 1/7 : FROM golang:latest
 ---> d817ad5b9beb
Step 2/7 : WORKDIR /go/src/go-app2
Removing intermediate container 816a33af9a01
 ---> bb3d6012e557
Step 3/7 : COPY . .
 ---> e38c75d754d3
Step 4/7 : ENV GO111MODULE=on
 ---> Running in 57345b25fb4f
Removing intermediate container 57345b25fb4f
 ---> d9500cf1f5cd
Step 5/7 : RUN go get -u github.com/labstack/echo
 ---> Running in 01dc8d6ebd6c
go: finding github.com/labstack/echo v3.2.2+incompatible
go: downloading github.com/labstack/echo v3.2.2+incompatible
go: finding github.com/labstack/gommon/log latest
go: finding github.com/labstack/gommon/color latest

... 略 

Creating goapp2_app_1 ... done
Attaching to goapp2_app_1
app_1  | 11:2:58 runner      | InitFolders
app_1  | 11:2:58 runner      | mkdir ./tmp
app_1  | 11:2:58 runner      | mkdir ./tmp: file exists
app_1  | 11:2:58 watcher     | Watching .
app_1  | 11:2:58 watcher     | Watching templates
app_1  | 11:2:58 main        | Waiting (loop 1)...
app_1  | 11:2:58 main        | receiving first event /
app_1  | 11:2:58 main        | sleeping for 600 milliseconds
app_1  | 11:2:59 main        | flushing events
app_1  | 11:2:59 main        | Started! (8 Goroutines)
app_1  | 11:2:59 main        | remove tmp/runner-build-errors.log: no such file or directory
app_1  | 11:2:59 build       | Building...
app_1  | 11:3:00 runner      | Running...

あとは、ブラウザでアクセス。

http://localhost:8080/

htmlの内容が表示されていたら成功です。

また、docker-composeを起動したまま編集してみましょう! リロードし、変更が反映されていたら大丈夫です。

Dockerコンテナの中へ

以下のコマンドでDockerコンテナの中に入って、ローカルとのファイルのシンクがされているか確認できます。

$ docker exec -i -t <container_name> bash

今回の例だと、ディレクト/go/src/<project_name>が存在し、 $GOPATHは、/goになっていることが確認できます。

まとめ

いつもホットリロードに悩まされていましたが、Freshは楽ですね! 他にもGoのプロジェクトで使用されているタスクランナーがあります。

github.com

github.com

少しdockerで個人的に気になることがあるので、解決したら更新します!

トラブルシューティング

私が試したことしか記載できませんが、以下で1発でブラウザ確認までいけました。

  1. go.modファイル作成(空でおk)

  2. goのヴァージョンを確認

私の場合、1.12系で大丈夫でした。他のヴァージョンは試してないのでわかりません。。

FROM golang:1.12-rc   

go.modファイル作成の理由としては、GO111MODULE=onにしているとgo.modファイルが設置されているディレクトリでのみgo getコマンドが実行できないためです。

以上.

【インフラ】クラウドについて考えてみた

だいぶ日が空いてしまいました。。。

今回はインフラについてこちらの本を元に学んでいる最中なので、記事にしてみました。 インフラといっても、ほとんどクラウドについての内容になっています。

インフラCI実践ガイド Ansible/GitLabを使ったインフラ改善サイクルの実現

インフラCI実践ガイド Ansible/GitLabを使ったインフラ改善サイクルの実現

まずは、歴史から

インフラというと、なんだか堅い印象を私は持っています。

社会人出たてで、自社開発が叶わず面談行ったりしているときにも、 1社インフラよりの業務ということでお話を聞く機会がありました。

今の35歳から上の方でサーバサイドとかインフラエンジニアをやっていた方だと、 営業先の帰りに電気屋に行って、サーバーを購入した!とかお話を聞きました。

現在だと、もはや物理サーバー(オンプレサーバー)を使用している会社は、クラウド(Cloud)に移行しているのではないでしょうか?

クラウドサービスでいうと、AWSGCPなどが有名ですね! 私が業界に入ってからだと、クラウドが当たり前で、会社に入ってもオンプレからクラウドへの移行後だったり、 移行中やオンプレはわずかなんて会社が多かったです。

そんなこんなで、ビジネス面ではどういった動向がみられるのか調べてみました。

それぞれ、リソースの単価利用期間リードタイムをメモしました。 (引用:技術書インフラCI)

f:id:o21o21:20181010112044p:plain:w300

メインフレーム

この時代だと、主に銀行などのシステムで活用されていたようです。 きっと大企業のインフラくらいだったのでしょう。

オープンシステム

この頃から、今でも馴染みのあるWindowsUNIX系のOSのが登場しました。 一般な業務システムは、インターネットに接続されたサーバーとして活用されていきます。

クラウド

そして、現代のクラウドですね。 最近では、スマートスピーカーなど、Iotなんかは従来のITの領域を超えてきているといってもいいでしょう。

ここまでで、クラウドという単語を多々使用していますが、

そもそもクラウドとはなんなのか?ということです。

エンジニアの方なら説明できるでしょう。 ここでは詳しくは取り上げませんが、簡単に説明します。

クラウドとは?

クラウドとは、英語ではという意味を指してCloudと言います。 ただし、英語の場合、"Cloud ○○" と何か指すときには言うようですね。(例: Cloud Service, Cloud Computing...)

ちょっと断言できないのですが、日本でいうクラウドは、英語で(正式に)いうクラウド コンピューティングにあたるようです。 それは英語で単にCloudというと、空にある雲という意味にも英語圏の方はとれますよねw 日本語では、クラウド=CloudComputingという認識かな?

まあ、そんな細かいことは置いときます。

(言葉って難しい...)

クラウドとは、簡単に、

インターネットを通じて、ITリソースを必要なときに、必要な分だけ利用するという考え方」のことです。

うむ?どいうことや?

「ソフト(Excelとか)、ハードを購入しなくても使用できる」ということ。

これでなんとなくイメージしやすくなったのではないしょうか。

つまり、GmailEvernoteなどのサービスが該当します。

例えば、Gmailの場合、PCに特別アプリをインストールしたり、クレジットカードを登録して課金して使用するものではなく、オンラインでブラウザさえ使用できればメールのやり取りが可能ですね。

こうしたサービスを、クラウド SaaSとして提供されるものです。 他にも PaaS (Dockerなど)や、 IaaS (AWSなど)という種類を分割してクラウドサービスを分割できます。

そして今回は、この記事の文頭で言った通り、インフラについて学んでいるので、 IaaSの部分がメインになってきます。

さて、AWSが世界的にも有名サービスですが、 いったいどうして物理サーバーを購入しないでAWSの利用者はサーバー(EC2とかのインスタンス)を起動、ターミネイトしたりしているのでしょうか??

もちろんAWSの人たちが、サーバーを逐一起動させているわけではありませんwww (そんなことしてたらAWSの社員はいくらいても足りませんねww)

仮想化

こうした疑問のほとんどが、仮想化で賄われています。 例えば、1台の物理サーバーで複数台の仮想的なサーバーを運用します。

つまり、AWSでは利用者がインスタンスを作成するAPIを叩くと、AWSの世界各国にあるデータセンターの物理サーバーがクラウドサーバー(仮想サーバー)を起動させ、運用がすぐに可能になるということです。

この時のサーバーのスペックなどによって、きっと起動させるサーバーは異なるでしょうが、一気に複数台のサーバーを起動させることも容易になっています。

うん、アマゾンはすごいな〜。 なので、アマゾンの技術者は物理サーバーをメンテすることはありますが、AWSの利用者は物理サーバーをメンテナンスをすることはありません。 オンプレの場合、物理サーバーを設置する場所もセキュリティ上の都合で選ばなくてはなりませんが、クラウドならアマゾンの社員が物理サーバーの保守をしているので、その心配はないということです。世界各国にあるデータセンターの場所は公開されていないですが、日本国内にも存在してます。

そのうち、サーバーの仮想化についてもより詳しくみていきたいと思います!

話を戻します!w

スピード感!

こうした技術の発展で、QCD (Quality,Cost,Delivery)という考え方も変化しています。 なにかシステムを構築する際、QCDの評価軸に沿わないことが多々あります。

AWSのようなサーバーを利用うる場合、意識するのはFFFです。 これは「Fast Fast Fast」です!w

スピード感を持って試行錯誤し、結果的に効率的になり、品質の良い構築が可能になるというこです。 これは私も感じています。 AWSですが、インスタンスの起動はあっというまく間なので、 いろいろ試していた結果、「こっちの方法のほうがうまくいくな!」とか早い段階で気づくことができたりします。

まとめ

今回はほとんど紹介した本の内容には載ってないものになっていますが、 要は基本的なところを抑えた記事になります。

クラウドエンジニアやこれからのインフラエンジニアというのは、技術の移り変わりで 従来設定に時間が取られていたところを簡単に設定できるようになりました。

おかけで仕事が減ったように感じますが、エンジニアとしての価値を上げていかなければなりません。 それは、自動化であったり、従来はできなかったことに挑戦したり、研究したりする時間があるということです。

業務自体と手法も変動しますが、概念や考えた自体も見直し、(違う職種の方などに)共感してもらうことも大切だと思います。

次回は、具体的に自動化について書いていけたらと思います!!

以上.

【macOS】High Sierraでダークモードにした

先日Xcodeをインストールする関係で、OSのアップデートをしました。 けっこう時間がかかりましたが、ダークモードが使用できるとのことだったので、さっそく使用してみることにしました。

今年の頃に、macOS Mojaveという新しいOSが発表されるそうですが、 そのmacOS Mojaveには、完全にダークモードが追加されるようです。

なので、今はベータ版といったところでしょうか? まあ、日頃の操作で困るところがなければインストールしてみてもいいかもしれません。

ちょっと見にくいかもしれませんが、画面上部のメニューが暗くなりました。

f:id:o21o21:20180827122013p:plain

Dockの方も暗めになったかな?? 長時間使用するので、少しで暗い方が助かる...

ダウンロード - macOS High Sierra 10.13.6 統合アップデート

Chrome

私はChromeでもファイルを読み込ませて、GoogleEngineの検索結果画面を白色から変更しています。

そこまでするか!?と思う方もいるかと思いますが、ちょっとでも暗くしたい...ww

f:id:o21o21:20180827122441p:plain

これはChromeプラグインで簡単に設定できます。 ただし、調べたら以下のようなコメントがしてあったので、ここで紹介するのは控えますw

この拡張機能は Chrome ウェブストアのポリシーに違反しています

ターミナル

今までターミナルやiTermからgitで管理されているディレクトリに移動すると、 ブランチ名を表示するようにしていました。

今回、OSのアップデートをかけたら表示されていないことに気づきました。

xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun

そして、gitコマンドを叩くとこんなエラーが。。

調査したところ、xcode-selectとあんるものをインストールすれば解決するとのこと。

$ xcode-select --install

ちょっと時間がかかりましたが、上記のコマンドでインストール完了したら、元通りになりました。 xcode-selectについて、詳しくはこちらの記事を参照してみてください。

以上.

【海外消費者向けEC】越境型ECサイトを考える

今回は定性的な話です! あんまり意識したことなかったのですが、海外消費者向けのサービスについて少し考えてみます。

f:id:o21o21:20180814180125j:plain

まえおき

ECサイトなんか運営していると、海外在住の方に向けて商品を売りたいと思うのは当たり前な世の中ですね。 また、消費者側も日本のあの商品が欲しいと思っている方が多いと思います。

2020年のオリンピック開催に向け、外国人の観光客も増え、より日本の文化に触れたり、 かわいい商品買って、自国に帰ってからも関心が高くてまた購入したい!など、 ECの競争はより国外に向けれていくのかなとか思います。

ECの業界の革命

最近EC界の帝王Amazonが起こした革命をご存知でしょうか?w

それは、International Shoppingというものです。

技術者でない方にはあまりこの凄さが伝わらないのですが、 簡単に言うと、アメリカで取扱されている商品を日本円で購入できるというもの。

言い換えると、www.amazon.comwww.amazon.co.jpの境界線がなくなった、と言えるのではないでしょうか。

日頃から個人輸入が行えるサービスを利用している方は、そんなに驚くこともないだろう。 Paypalとかebayなどのサービスを使用していたり、仮想通貨なんか使用している人も、 世界共通通貨のようなカタチで商品の売買に慣れているので、まあ世の中そんな流れになってきているかんじですね。

まあ、仮想通貨までいくと少し、ここで話をする主題とズレるのですが、 現状、国内向けECサイトを運営していて、(しかも自前でソースコードを管理していて) これから海外消費者に向けてサービスを展開したい!みたいなところに目を向けてみました。

海外消費者向け購入発送代行サービス

国内にも手軽(企業向けかな?)に利用できるサービスがあるようです。

海外消費者向け購入発送代行サービスと呼ばれるサービスで、 既存のEC既存サイトに簡単なバナーを設置するだけで、商品の海外発送まで代行してくれるという。

自分は初めて知ったので、便利だなーと感心。 たしかに、エンジニアが不足している企業だったりすると助かるサービスかもしれませんね〜。ん〜。

BuySmartというサービスも同様で、基本的にHTMLをviewに埋め込むだけで使用できるという。

手軽さでいうとたしかに助かりますね!

ただ、こうした越境ECになると一番気をつけないといけないのは、発送ではないでしょうか。

購入できても、お客様に商品を届けないと意味がないですよねw

この商品に関して、国内なら簡単では国外に向けて発送になると法律的な面で意外と大変です。

郵送禁止物品として扱われるモノは勿論法律違反となります。 例えば、爆発物・危険物(ライターとかも対象になるのかなあ)や生きた生物などなど。

法律だけでなく、条約にも関係してくるので、いちいち調査する手間がかかります。

ですが、代行サービスではそうした手間も省けるものがほとんどです。 購入された商品を、代行サービスに届けるだけで、あとはお任せできます。

んーこれは楽だな〜

技術者ならば、発送はおれの仕事ではないと考える人も少なくないのでは?w

少し技術的な話

こうしたサービスを利用する際に、考慮しておきたいのはIPの制限とかではないでしょうか? AWSでは、CloudFront (クラウドフロント)というサービスがあります。

CloudFrontには、地理的ディストリビューションの制限が可能です。

AWSコンソール上で、簡単に国単位で設定がポチポチでできてしまいます。

ECサイトを運営する際に、海外にも展開するのはいいですが、 例えばアメリカは駄目とか東南アジアのみにしたいとかあるかと思います。

そうした場合にCloudFrontを利用するとよさそうです。

また、言語化についても考慮しておきたいですね。(一応) 私も経験があるのですが、納期に迫られるとかなり効率の悪い多言語対応をしてしまいます。

負の遺産というやつですねwww ソースコードも読みにくくなるし、いいことないです。 viewで判定したり、そのためにテーブル作成して....とか

今ではそうしたゴチャゴチャにならないように色々サービスが提供されているはずです。 例えば、Amazon TranslateなんかはAPIで自動翻訳してくれます。

最近日本語も対応したようです。 少し文法的に変化もしれませんが、負の遺産を産むよりましかもしれません。 Amazon Translateのヴァージョンアップでより良くなるのを待つほうが楽ですね。

言語で用意されている環境変数とか利用すればいいとか、方法は様々ですが、 できるだけシンプルに将来を見据えて設計していくことがかなり重要といえるでしょう!

【AWS】EC2のリタイア!?

今回はEC2について、ちょっとあんまりみない現象なのかな?と思い調べてみました。

リタイア!?

なにが起こったかというと、こんなメッセージがEC2のメニューで表示されていた。

f:id:o21o21:20180814120153p:plain

なぬ!ってかんじでしたw

このインスタンスAWSコンソールをいじっていたところ、 上記のメッセージを確認。。。

もう少し詳しく調べてみましょう。

詳しく

公式にはこう定義されていました。

インスタンスをホストしている基盤のハードウェアで回復不可能な障害が検出されると、AWS によってインスタンスのリタイヤが予定されます。

ふむふむ。ってことは、なんか致命的なエラーでも出ているのか?

再度EC2のメニューから確認してみたが、そんなことはなさそう。 EB(Elastic Beanstalk)から立てられたインスタンスだったので、ヘルスも確認してみたが別に普通。

なんでだろう?ということで、調査するとどうやらメールが届いているらしい。

確認してみるとこのようなタイトルのメールが届いている。

[Retirement Notification] Amazon EC2 Instance scheduled for retirement.

これですなw

詳しく本文を読んでみると、ハードウェア(インスタンス)の劣化が原因で、リタイアの設定がなされたようです。 納得ですね、特に何もインスタンスに対して変更をかけていないと勝手に起こるものらしい。

対応策

今回はEBなので、ポチッとインスタンスもう1つ増やしておけばOK。 対応策については、ルートデバイスタイプによりけりみたいです。 以下に公式ドキュメントを貼っておきます。ドキュメントの下部にルートデバイスタイプ別のアクションが載っています。 それで、対応してみるのがよさそうです。

docs.aws.amazon.com

くれぐれも日付を過ぎてからでは、面倒なことになりかねないので、メールをちゃんとフィルタしておこうと思いました! いや!そもそもインスタンスをきちんと管理していなと駄目ですねww

ただ沢山あると忘れがちになりますが。。。

以上.