K4750.NET

Angularでcowsayしてみた

オライリーの「Docker」本で初めてcowsayコマンドの存在を知った・・・Angularで出来るかな?


1.Angularプロジェクト作成

いつものやつ。

$ ng new cowsayangular7

2.cowsayインストール

ずばりcowsayパッケージがあるので、これをインストールする。

$ cd cowsayangular7
$ npm install --save cowsay

3.AppComponent変更

とりあえず、app.component.htmlは超シンプルにして、

<pre>{{title}}</pre>

app.component.tsにimportを追加して、title行を変更し、

import { Component } from '@angular/core';
import { say } from 'cowsay/build/cowsay.es.js';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = say({ text: 'Hello Angular7 World!'});
}

app.component.scssはこんな感じか。

pre {
  font-family: "Lucida Console";
  font-size: 32px;
}

4.Cow say “Hello Angular7 World!”

実行してみる。

$ ng serve --open

出た出た^^

Hello Angular7 World

DockerfileのCOPYの動きを確認してみる

DockerfileのCOPY命令がファイルの内容に変化がなければキャッシュを使うことは分るが・・・ファイルが消えた時等はどうなるのだろう・・・ということで試してみた。


1.サンプルファイル

Dockerfile
src\
   a.txt
   b.txt
   c.txt

Dockerfileの内容:

FROM alpine:latest
COPY src dst

2.初回ビルド

$ docker build -t copytest .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM alpine:latest
latest: Pulling from library/alpine
4fe2ade4980c: Already exists
Digest: sha256:621c2f39f8133acb8e64023a94dbdf0d5ca81896102b9e57c0dc184cadaf5528
Status: Downloaded newer image for alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> 7a3d51886012
Successfully built 7a3d51886012
Successfully tagged copytest:latest

COPY結果を確認してみる。

$ docker run --rm copytest ls -l /dst
total 0
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 a.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 b.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 c.txt

3.2回目ビルド

ホスト環境を何も変えず、2回目を実行してみる。

$ docker build -t copytest .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> Using cache
 ---> 7a3d51886012
Successfully built 7a3d51886012
Successfully tagged copytest:latest

COPYは実行されず、キャッシュが使われている。よって、COPY結果も変わらず。


4.ファイルを追加する

まずはファイルを追加してみる。

Dockerfile
src\
   a.txt
   b.txt
   c.txt
   d.txt <- ファイルを追加する

ビルドを実行してみると・・・

$ docker build -t copytest .
Sending build context to Docker daemon  4.608kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> 4584e2974830
Successfully built 4584e2974830
Successfully tagged copytest:latest

キャッシュは使われずに、COPYが実行されている。結果を確認してみる。

$ docker run --rm copytest ls -l /dst
total 0
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 a.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 b.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 c.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 d.txt

5.追加したファイルを削除する

先ほど追加した d.txt を削除して、ビルドを実行してみると、

$ docker build -t copytest .
Sending build context to Docker daemon  4.096kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> Using cache
 ---> 7a3d51886012
Successfully built 7a3d51886012
Successfully tagged copytest:latest

予想に反して(?)、(d.txtを追加する前に作成した)キャッシュが使われている。賢い^^;


6.さらにファイルを削除する

さらに c.txt を削除して、ビルドを実行してみると、

$ docker build -t copytest .
Sending build context to Docker daemon  3.584kB
Step 1/2 : FROM alpine:latest
 ---> 196d12cf6ab1
Step 2/2 : COPY src dst
 ---> c8f23fe46a11
Successfully built c8f23fe46a11
Successfully tagged copytest:latest

ファイルが消えたことを検知して、COPYが実行された。dstの内容は・・・

$ docker run --rm copytest ls -l /dst
total 0
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 a.txt
-rwxr-xr-x    1 root     root             0 Oct 27 14:25 b.txt

期待通りの動きだ^^

オライリーの「Docker」のサンプルが動かなかったので修正してみる

約2年前の2016年8月に発行されたオライリー「Docker」。5章「開発でのDockerの利用」を実際に手を動かして確認してみたところ、所々動かない個所があったので修正してみる。


1.「5.1 “Hello World!”」

コンテナ内で実行してみたがエラーになる・・・どうやら2行目がインデントされているのが問題のようだ。

from flask import Flask
    app = Flask(__name__) 

@app.route('/') 
def hello_world():
    return 'Hello World!\n'

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')

下記 Dockerfile は問題なし。

FROM python:3.4
RUN pip install Flask==0.10.1
WORKDIR /app
COPY app /app
CMD ["python", "identidock.py"]

コンテナのビルド&起動も問題なし。

$ docker build -t identidock .
$ docker run -d -p 5000:5000 identidock

curlコマンドによる動作確認は・・・Windows環境なのでcurlがないのと、コンテナ内へホスト環境からアクセスするには上記Pythonコードの「host=0.0.0.0」をコンテナに割り当てられたIPアドレスに書き換える必要(?)があるようなので・・・せっかくなのでcurlがインストールされたDockerイメージを使って動作確認してみる。

$ docker run --rm -it --entrypoint /bin/sh byrnedo/alpine-curl
/ # curl http://172.17.0.3:5000/
Hello World!

IPアドレス「172.17.0.3」は、identidockイメージから起動されたコンテナのアドレス。本来ならば –link 等を使ってもっとエレガントにやるのだろうが・・・。続いて、アプリケーションサーバ uWSGI を使うためのDockerfile。

FROM python:3.4
RUN pip install Flask==0.10.1 uWSGI==2.0.8
WORKDIR /app
COPY app /app
CMD ["uwsgi", "--http", "0.0.0.0:9090", "--wsgi-file", "/app/identidock.py", \
     "--callable", "app", "--stats", "0.0.0.0:9191"]

uWSGIのコンパイル(?)エラーが出力されて、イメージのビルドに失敗する。。Pythonのバージョンを変えたり、FlaskやuWSGIのバージョン指定を外したりしても改善しなかったので、結局UbuntuをベースにPython3.6をインストールするやり方にしてみた。

FROM ubuntu:18.04
RUN apt-get update -y && apt-get install -yq python3-pip python3-dev wget && \
    wget https://bootstrap.pypa.io/get-pip.py && python3.6 get-pip.py && \
    pip install Flask uWSGI
WORKDIR /app
COPY app /app
CMD ["uwsgi", "--http", "0.0.0.0:9090", "--wsgi-file", "/app/identidock.py", "--callable", "app"]

CMD行も”–stats”あたりでエラーが出てコンテナが起動できなかったので、パラメタを削除して起動するようにした。

Angular7 in Docker

Docker for Windows(Docker Community Edition for Windows)をWindows 10 PCへインストールしたので、試しにAngular7をコンテナ内でビルドし、実行してみます。


1.Dockerfile を書いてみる

Node.jsがインストール済みのイメージファイルをベースにして、Angular CLIのインストールと新規プロジェクトの作成をすればよいので・・・こんな感じかな?

FROM node:10-alpine
WORKDIR /work
RUN npm install -g @angular/cli@7.0.3
RUN ng new --defaults angular7
WORKDIR /work/angular7
CMD ng serve

2.ビルド&実行

作った Dockerfile を使って ng new まで実行したイメージファイルを作り、実行してみる。

$ docker build -t angular7 .
$ docker run -p 4200:4200 --name angular7 angular7

上手くいったようだが・・・http://locahost:4200 を叩いてもアクセスできず。結局、いろいろ試したところ、DockerfileのCMD行を

CMD ng serve --host `hostname`

へ変更して再度ビルド&実行すると、ホストPC上のブラウザからは http://127.0.0.1:4200 でアクセスできることが判明。Docker for Windows 固有の問題なのだろうか・・・?とりあえず動いたから良しとしよう^^;


3.Yarn 発見

ふと気づいたのだが・・・

$ docker exec -i -t angular7 /bin/sh
/work/angular7 # yarn -v
1.10.1
/work/angular7 # which yarn
/usr/local/bin/yarn

Ultra Fastを謳う^^; Yarnコマンド(現時点の最新Stable版)が/usr/local/binにインストールされていた。早速、Dockerfileを書き換えてみる。

FROM node:10-alpine
WORKDIR /work
RUN yarn global add @angular/cli@7.0.3
RUN ng new --defaults --skipInstall=true angular7
WORKDIR /work/angular7
RUN yarn
CMD ng serve --host `hostname`

こんな使い方では速度を体感することもなく・・・動いたので良しとしよう^^;;

Angular7プロジェクトをFirebaseでホスティングしてみる

Angular7プロジェクトをFirebaseのHostingへデプロイして公開してみる。


1.Node.js&npmインストール

Node.js 本家 から推奨版(現時点では8.12.0 LTS)をダウンロードしてインストールする。


2.Angular CLIインストール

現時点の最新版(7.0.3)をインストールする。旧バージョンがインストール済みの場合はuninstallおよびcache verifyも実行する。

$ npm uninstall -g @angular/cli
$ npm cache verify
$ npm install -g @angular/cli@7.0.3

3.Firebase CLIインストール

Firebase CLIをインストールの上、Firebaseへログインする。

$ npm install -g firebase-tools
$ firebase login

ブラウザが開くので、Firebaseを利用するGoogleアカウントを選択(またはログイン)する。成功すれば、

Waiting for authentication...

+  Success! Logged in as xxxxxxxxxx@gmail.com

のようにコンソールに表示される。


4.Firebaseプロジェクト作成

https://console.firebase.google.com にて、Hosting用のプロジェクトを作っておく(今回は「angular7」を作った)。


5.Angularプロジェクト作成、ビルド

まずはAngularプロジェクト「angular7」を作る。

$ ng new angular7
? Would you like to add Angular routing? No
? Which stylesheet format would you like to use? SCSS   [ http://sass-lang.com   ]
CREATE angular7/angular.json (3877 bytes)
CREATE angular7/package.json (1315 bytes)
...

次に、デプロイ用のファイル一式を「angular7/public」ディレクトリへ生成する。

$ cd angular7
$ ng build --prod --output-path=public

6.FirebaseのHostingへデプロイする

angular7ディレクトリをそのままFirebaseのプロジェクトとして初期化する。カレントディレクトリをangular7のままで、以下を実行する。

$ firebase init

質問に対しては以下のように回答した(生成済みのpublic/index.htmlを上書きしないよう注意)。「angular7-xxxxx」はFirebaseプロジェクト作成時に割り当てられたプロジェクトIDであり、「xxxxx」部分は作成の都度、固有の文字列が割り当てられる。

? Are you ready to proceed?
 -> Yes
? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices.
 -> Hosting: Configure and deploy Firebase Hosting sites
? Select a default Firebase project for this directory:
 -> angular7-xxxxx (angular7)
? What do you want to use as your public directory?
 -> public
? Configure as a single-page app (rewrite all urls to /index.html)?
 -> No
? File public/index.html already exists. Overwrite?
 -> No

そしてデプロイを実行する。

$ firebase deploy
=== Deploying to 'angular7-xxxxx'...

i  deploying hosting
i  hosting[angular7-xxxxx]: beginning deploy...
i  hosting[angular7-xxxxx]: found 8 files in public
+  hosting[angular7-xxxxx]: file upload complete
i  hosting[angular7-xxxxx]: finalizing version...
+  hosting[angular7-xxxxx]: version finalized
i  hosting[angular7-xxxxx]: releasing new version...
+  hosting[angular7-xxxxx]: release complete

+  Deploy complete!

Project Console: https://console.firebase.google.com/project/angular7-xxxxx/overview
Hosting URL: https://angular7-xxxxx.firebaseapp.com

7.動作確認

Firebaseへデプロイ時に表示されたHosting URLへアクセスすると・・・

Welcome to angular7!

無事表示されただろうか。