20201112のdockerに関する記事は10件です。

RailsのDocker化 〜その1〜

はじめに

Dockerはなんとなく聞いたことがあって、使うと便利なんだなーという印象があると思います。Ruby on RailsをDocker化するとどんなことが便利になるのか、検証していきたいと思います。

Dockerとは

エンジニアでコードを書いたことがある人なら経験があると思いますが、開発環境を作るまでに時間かかりませんか?
* これが足らない!ってなんかエラーが出て進まない!!
* 私はMacだけど、○○さんはWindowsで環境構築してるから勝手が違う!!
* 先輩に私のときはこれでうまく動いたって言われた、、、。

そこでDockerの登場

簡単にいうと、誰かが作ってくれたdockerのimageを使えば、環境に作用されず、ぽんっとコマンドを叩くだけでlocalに開発環境が出来てしまいます!!便利!!

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

[AWS][docker] docker build 時にインターネット接続に失敗

AWS EC2 上で docker イメージをビルドしようとして、ハマったので覚え書き。

現象

docker イメージのビルドで以下のエラーになった。
内容は fluentd のイメージにプラグインの gem を追加するというもの。

$ docker build . --no-cache
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM fluent/fluentd:v1.11.4-2.0
v1.11.4-2.0: Pulling from fluent/fluentd
df20fa9351a1: Pull complete
5bbb4150a5a0: Pull complete
0a2f393cb307: Pull complete
b1dea35b5d99: Pull complete
65de893ed157: Pull complete
Digest: sha256:0c6ae6c72902cbc3a4f60bc15069cb89fd72b57391bff150960a6f911361d6c9
Status: Downloaded newer image for fluent/fluentd:v1.11.4-2.0
 ---> 7bcbcb847e0d
Step 2/4 : USER root
 ---> Running in 79fb5c74b17f
Removing intermediate container 79fb5c74b17f
 ---> 03af9cdb324e
Step 3/4 : RUN gem install         fluent-plugin-cloudwatch-logs
 ---> Running in 1bcf43a8efb2
ERROR:  Could not find a valid gem 'fluent-plugin-cloudwatch-logs' (>= 0), here is why:
          Unable to download data from https://rubygems.org/ - no such name (https://rubygems.org/specs.4.8.gz)
ERROR: Service 'fluentd' failed to build : The command '/bin/sh -c gem install         fluent-plugin-cloudwatch-logs' returned a non-zero code: 2

rubygems.org に接続できないというもので、調べてみるとプロキシの設定が必要などの情報が出てくる。
が、ホスト上では接続できているので関係はなさそう。

サイトへの直接アクセスもできず、名前解決もできていない。
で、分かったのはネットワークインターフェースの eth0 がないこと。

$ docker build . --no-cache
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM fluent/fluentd:v1.11.4-2.0
 ---> 7bcbcb847e0d
Step 2/3 : USER root
 ---> Running in c80c0a20cd21
Removing intermediate container c80c0a20cd21
 ---> 16f2ba30695a
Step 3/3 : RUN ifconfig
 ---> Running in 1d9cb7d5e2ec
lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Removing intermediate container 1d9cb7d5e2ec
 ---> de98e34f64e7
Successfully built de98e34f64e7

ホスト側で見てみると docker0 がなく、docker network でデフォルトの bridge がいないことが分かった。

$ docker network ls
NETWORK ID          NAME                           DRIVER              SCOPE
2d9ce67d06f5        host                           host                local
9a455bcae53c        none                           null                local

確認

ホストの OS は Amazon Linux 2 (EKS-Optimized) ですが、別のサーバでは問題なくビルドできていたので、比べてみるとバージョンが違っている。

  • amazon-eks-node-1.11-v20190220 → ビルドできている環境
  • amazon-eks-node-1.17-v20201002 → ビルド失敗する環境

それぞれの docker のバージョンを見てみると、以下の違いがあった。

# ビルドできている環境
$ docker version
Client:
 Version:           18.06.1-ce
 API version:       1.38
 Go version:        go1.10.3
 Git commit:        e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
 Built:             Mon Jan 28 21:03:38 2019
 OS/Arch:           linux/amd64
 Experimental:      false
    :

# ビルド失敗する環境
$ docker version
Client:
 Version:           19.03.6-ce
 API version:       1.40
 Go version:        go1.13.4
 Git commit:        369ce74
 Built:             Fri May 29 04:01:26 2020
 OS/Arch:           linux/amd64
 Experimental:      false
    :

なお、ビルドできている方ではデフォルトの bridge ネットワークが存在している。

$ docker network ls
NETWORK ID          NAME                               DRIVER              SCOPE
2f3fd9d451c6        bridge                             bridge              local
cd2fe4f72dff        host                               host                local
f56d76b46acb        none                               null                local

この bridge の有無が docker build のエラー原因かは情報を見つけられなかったのですが、デフォルト bridge の有無の方向で調べてみると /etc/docker/daemon.json という設定ファイルが出てきたので上記のサーバで比較してみた。

ビルドできている環境

/etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "10"
  },
  "live-restore": true,
  "max-concurrent-downloads": 10,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Soft": 2048,
      "Hard": 8192
    }
  }
}

ビルド失敗する環境

/etc/docker/daemon.json
{
  "bridge": "none",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "10"
  },
  "live-restore": true,
  "max-concurrent-downloads": 10
}

bridge: none という設定が関係しそう。

対処

/etc/docker/daemon.json ファイルの bridge: none の設定を削除して docker サービスを再起動してみる。

$ sudo service docker restart

上記のコマンドでサービス再起動をしてもすぐ解決しなかった。
その後、stop、start と別にしたり、systemctl コマンドで操作したりしてるうちにデフォルト bridge ができた。

どうも、稼働中のコンテナがいたり、docker-compose で作られるネットワークがいるとダメなようで、すべてのコンテナを停止して、後から作られたネットワークも削除してから docker サービスを再起動したら設定が反映された。

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c4433dcfbe9b        bridge              bridge              local
2d9ce67d06f5        host                host                local
9a455bcae53c        none                null                local

先ほどの docker build を試してみると、eth0 もできてる。

$ docker build . --no-cached
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM fluent/fluentd:v1.11.4-2.0
 ---> 7bcbcb847e0d
Step 2/3 : USER root
 ---> Using cache
 ---> 15b06f798b72
Step 3/3 : RUN ifconfig
 ---> Running in 713f15663040
eth0      Link encap:Ethernet  HWaddr 02:42:AC:12:00:02
          inet addr:172.18.0.2  Bcast:172.18.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:180 (180.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

Removing intermediate container 713f15663040
 ---> 6d99f256433b
Successfully built 6d99f256433b

元の fluentd のビルドを試してみると、gem のダウンロードもできて、問題なくビルドができるようになった。

$ docker build . --no-cached
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM fluent/fluentd:v1.11.4-2.0
 ---> 7bcbcb847e0d
Step 2/4 : USER root
 ---> Using cache
 ---> a733f7c02648
Step 3/4 : RUN gem install         fluent-plugin-cloudwatch-logs
 ---> Running in 1d43a2226fb4
Successfully installed jmespath-1.4.0
Successfully installed aws-partitions-1.391.0
Successfully installed aws-eventstream-1.1.0
Successfully installed aws-sigv4-1.2.2
Successfully installed aws-sdk-core-3.109.2
Successfully installed aws-sdk-cloudwatchlogs-1.38.0
Successfully installed fluent-plugin-cloudwatch-logs-0.11.1
7 gems installed
Removing intermediate container 1d43a2226fb4
 ---> f7242c21bd02
Step 4/4 : USER fluent
 ---> Running in 7baaad7e3b2d
Removing intermediate container 7baaad7e3b2d
 ---> c39b2ddf48d9
Successfully built c39b2ddf48d9

ビルドエラーは解消できたのでひとまずは完了ですが、なぜ新しいバージョンの docker、OS 環境で bridge が無効化されているのかが分からない。

デフォルトの bridge は作るべきではないという情報も見かけたのだけど、なぜダメで、bridge を作らないのであればどうすべきかというはっきりとした情報が見つけられなかった。

あるいは EKS-Optimized なイメージなので、通常はランタイムのみの利用で docker build の実行を想定していないのかもしれない。

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

VScodeでDockerのコンテナから抜ける設定

はじめに

デバッグするときにDockerにattachした際、デタッチ(コンテナから抜ける)するときに
Ctrl+PCtrl + Qを使うと思います。

しかし、VScodeではすでにこれらのショートカットキーが登録されていてそちらが優先されてしまいます。
VScodemでデタッチできるように、VScodeのショートカットキーが効かないように設定を変更してみました。

設定

ショートカットを確認するとctrl+Pctrl+Qがすでに登録されていることが確認できます。
スクリーンショット 2020-11-12 16.02.01.png

VScodeのkeybindings.jsonに下記を記載します。(command+Pでファイル検索を開き、>keybindings.jsonと打つと開きます!)

すでに設定されているcommandに-をつけることでctrl+Pctrl+Qのショートカットキーを削除できます。

keybindings.json
{
    "key": "ctrl+P",
    "command": "-workbench.action.quickOpenSelectPrevious"
  },
  {
    "key": "ctrl+Q",
    "command": "-workbench.action.quickOpenView"
  }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

UbuntuのDockerコンテナでファイル内容をコピペ

今使っているDockerコンテナでファイル内容をコピペしようとしたときのことです。

Macだとpbcopyでファイル内容のコピペができます。

$ pbcopy < helloworld.txt
// pbcopy < コピーしたいファイル

Ubuntuだとxselを使うといいです。

$ apt-get -y install xsel
$ xsel -b < helloworld.cpp 
// xsel -b < コピーしたいファイル
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Dash(+Docker)で機械学習アプリを作ってみたpart2 ~Dashの基本的な書き方~

はじめに

 PythonのWebアプリフレームワークDashを用いて簡単な機械学習アプリを作成したため、その学習記録として本記事を書きました(成果物はこちら)。前記事(part1)では、DockerでのDashの環境構築について紹介しました。本記事ではそれに続き、Dashアプリのメインとなるapp.pyの書き方について、二大要素であるLayout(アプリの外観を設定する部分)とCallback(対話的な動きを設定する部分)を中心に紹介していきます。基本的には公式のチュートリアルからの抜粋になるため、英語に抵抗のない方はそちらを読んでいただければと思います。また、HTMLやCSSについて、基本的な知識(Progateの無料で受講できる範囲程度)があると理解しやすいかと思います。

Layoutの書き方

 Layout部分ではアプリの外観を作っていきます。他のフレームワークではhtmlファイルを別で作成する場合が多いですが、Dashでは基本的に1シート(app.py)で作っていきます。Dashをインストールすると、HTMLタグを提供するパッケージdash_html_components、描画に必要なUIを提供するパッケージdash_core_componentsが自動的にインストールされ、これらを使ってLayoutを書いていきます。例として、環境構築で使用したものと同じapp.pyファイルを示します。

app.py
# ライブラリをインポート
import dash
import dash_core_components as dcc  #描画に必要なUIを提供するパッケージ
import dash_html_components as html #HTMLタグを提供するパッケージ

# 外部CSSのパスを指定
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

# アプリの起動。アプリ名を指定できる(この場合__name__=appになる)。外部CSSもここで指定する。
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)


######################### Layout部分 ####################################
app.layout = html.Div(children=[

    html.H1(children='Hello Dash'),
    html.Div(children='Dash: A web application framework for Python.'),
    dcc.Graph(
        id='example-graph',
        figure={
            'data':[{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                    {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}],
            'layout':{'title': 'Dash Data Visualization'}
        }
    )
])
########################################################################

# サーバーの立ち上げ
if __name__ == '__main__':
    app.run_server(host='0.0.0.0', port=5050, debug=True)

 dash_html_componentsには、HTMLのタグ(div, H1など)に相当する同じ名前のものが存在するため、それらを使ってHTMLライクに書いていきます。上のapp.pyのLayout部分はHTMLで書くと、下のようになります。

<div>
    <h1>Hello Dash</h1>
    <div>Dash: A web application framework for Python.</div>
    <div id="exampl-graph" class="dash-graph">
        <!-- 描画内容 -->
    </div>
</div>

 引数childrenに、表示させるテキスト部分(HTMLでタグに挟まれる部分)を与えます。また、この引数にchildren=[html.H3(), html.H5(), ...]のようにリストを渡すことで、HTMLの入れ子構造を作ることができます。引数idではHTMLと同様に任意でidを指定することでき、idは主に後で紹介するCallbackの際に使用します。
 CSSの記述も同じシート上で行い、引数styleに辞書型で指定します。例えば、'Hello Dash'の部分に

html.H1(children='Hello Dash', style={'color':'red'})

のように追記すると、'Hello Dash'が赤く表示されます。
 プルダウン、チェックボックス、ボタンなどを実装するにはdash_core_componentsを使用します。全て紹介するとキリがないため割愛しますが、公式サイトのコード例を見ればとても簡単に実装できます。
 グラフの描画も同様にdash_core_componentsを使いdcc.Graph(figure=...)のように作っていきます。Plotlyの図を使用したい場合は、こちらにコード例が多く載っていますので、参考にしながら引数figureで指定します。その際、Plotlyが提供するパッケージのimportを記述する必要があるので注意してください。インストールはDashのインストール時にすでにされていると思います。

Callbackの書き方

 Callback部分では、 対話的な動きを設定していきます。例として、テキストボックスに入力された文字を、文章に反映させる簡単なアプリを取り上げます。

app.py
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output

app = dash.Dash()

######################### Layout部分 ####################################
app.layout = html.Div([
    html.H6("Change the value in the text box to see callbacks in action!"),
    html.Div(['Input:',
        # テキストボックス部分
        dcc.Input(
            id='my-id', 
            value='initial value',  #初期値(指定しなくても可)
            type='text'
        )
    ]),
    # 文章を表示させる部分
    html.Div(id='my-div')
])
########################################################################

######################### Callback部分 ##################################
@app.callback(
    Output(component_id='my-div', component_property='children'),
    [Input(component_id='my-id', component_property='value')]
)
def update_output_div(input_value):
    return 'Output: "{}"'.format(input_value)
########################################################################

if __name__ == '__main__':
    app.run_server(host='0.0.0.0', port=5050, debug=True)

スクリーンショット 2020-11-12 14.02.22.png

 CallbackはLayoutの下に、@app.callbackというデコレーターを使って書いていきます。デコレーターが何かわからなくても問題ありませんが、勉強したい方はこちらの記事がわかりやすいです。また、Callbackで使用するInputOutputもimportしておきます。

Callbackの動きはとてもシンプルで、
   ①Inputで指定した要素がその下で定義した関数の引数として渡される
   ②その関数の出力がOutputで指定した要素に渡される
という2ステップです。InputとOutputの指定は、idとpropertyを指定することで行います。今回の例だと、①idが'my-id'のvalueの値、即ちテキストボックス部分であるdc.Input()のvalueの値(=UI操作で入力された値)がupdate_output_div関数の引数(input_value)として渡され、②この関数の出力結果('Output:〜')がid='my-div'であるhtml.Div()のchildrenに渡されます。これにより、テキストボックスに入力された文字列が下の'Output:'以降に反映させることができます。

※Callbackの注意点
 1つのCallbackにつき、Outputは1つしか設定できません。あるInputを複数のOutputに反映させたい場合は、その数だけCallbackを記述する必要があります。一方で、Inputは下のように複数受け取ることができます。

@app.callback(
    Output(component_id='id_3', component_property='children'),
    [Input(component_id='id_1', component_property='value'),
     Input(component_id='id_2', component_property='value')]
)
def func(input1, input2):
    return ...

おわりに

 Dashの基本的な書き方を紹介しました。一見複雑そうなアプリも基本的にはこのCallbackを組み合わせることで作ることができ、逆にこの仕組みさえ理解すれば、あとは公式のサンプルコードを見ながら様々なことに応用することができると思います。次の記事では応用例として、実際に私が作成した機械学習アプリを部分的に抜粋しながら紹介したいと思います。

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

Dash(+Docker)で機械学習アプリを作ってみたpart1 ~環境構築と動作確認~

はじめに

動機

 機械学習を勉強する中で何か成果物を作ってみたいと思い、また可視化ツールであるPlotlyも触ってみたいと思っていたため、Plotlyが使われているDashでのアプリ開発に取り組みました。実際に作成した成果物がこちらになります。学習記録を残す目的でこの記事を書きました。アプリ開発は初心者ですが、よろしくお願いいたします。

対象読者

 Dashでのアプリ開発に興味のある方や、機械学習やデータサイエンス関連の成果物を作りたいが何を作れば良いか悩んでいる方の参考になれば幸いです。Dockerの知識があることを前提としています。Dockerについては、かめさんのブログ(深く学ぶならUdemy講座)が分かりやすくておすすめです。

Dashとは?

 DashはPythonのWebアプリケーションフレームワークの一つです。Plotly社が開発したオープンソースのフレームワークで、他にもR言語などで利用することができます。PythonのWebアプリフレームワークではDjangoやflaskなどが有名ですが、Dashは可視化に特化している点が特徴的です。Dashのバックエンドではflask, Plotly.js, React.jsが動いており、核となるPlotly.jsはJavaScriptベースの可視化ツールで、対話的な操作が可能な図を描画することが可能です。
 まとめると、Dashを使うことで、JavaScriptの知識なしに動的なダッシュボードアプリを簡単に作成することができます。言葉で説明してもイメージが沸きにくいと思うので、ぜひ公式サイトで公開されているアプリのサンプルを見てみて下さい。機械学習系のアプリも多くあり、また全てではありませんがGitHubにソースコードも公開されているため、機械学習のアウトプット法の一つとして参考になると思います。

環境構築

 環境構築は、こちらの方の記事を参考にDockerで行いました。Dashアプリ用のディレクトリ(今回は'Dash_App')内に以下のファイルを用意します。

<ディレクトリ構成>
Dash_App/
  ├ app.py
  ├ Dockerfile
  └ docker-compose.yml
Dockerfile
FROM python:3.7.3
USER root

RUN apt-get update
RUN apt-get install -y vim less
RUN apt-get install -y zsh less
RUN pip install --upgrade pip
RUN pip install --upgrade setuptools

RUN pip install \
    dash==1.16.3 \
    pandas \
    category_encoders \
    scikit-learn

ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8

EXPOSE 5050
CMD ["bash"]
docker-compose.yml
version: '3'
services:
  dash-app:
    restart: always
    build: .
    container_name: 'dash-app'
    ports:
      - "5050:5050"
    working_dir: '/root/'
    tty: true
    volumes:
      - .:/root/src/
      - ~/.zshrc:/root/.zshrc

 app.pyにはアプリの内容を書いていきます。まずは動作確認のため、公式チュートリアルにあるコードをコピペしておきます。

app.py
import dash
import dash_core_components as dcc 
import dash_html_components as html

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div(children=[

    html.H1(children='Hello Dash'),
    html.Div(children='Dash: A web application framework for Python.'),
    dcc.Graph(
        id='example-graph',
        figure={
            'data':[{'x': [1, 2, 3], 'y': [4, 1, 2], 'type': 'bar', 'name': 'SF'},
                    {'x': [1, 2, 3], 'y': [2, 4, 5], 'type': 'bar', 'name': u'Montréal'}],
            'layout':{'title': 'Dash Data Visualization'}
        }
    )
])

if __name__ == '__main__':
    app.run_server(host='0.0.0.0', port=5050, debug=True)

 サーバを立ち上げるコードの部分(最下行)でhost='0.0.0.0', port=5050を追記して指定していることに注意してください。ファイルの作成が終わったら以下のコマンドでコンテナを立ち上げます。

$ docker-compose up -d --build

 コンテナが立ち上がったら、以下のコマンドのようにコンテナに入ってapp.pyを実行します。※dash-appは、docker-compose.ymlで指定したコンテナ名になります。

$ docker-compose exec dash-app zsh -c "python src/app.py"

 問題がなければアプリが起動します。ブラウザからlocalhost:5050にアクセスし、下のようなアプリ画面が表示されれば成功です。※「control + C」でアプリを終了します。
スクリーンショット 2020-11-12 0.27.48.png

おわりに

 DockerコンテナでのDashの環境構築方法を紹介しました(とは言っても別の記事を見ながらDockerfileを少し修正しただけですが...)。一番面倒な環境構築がさくっとできるので、やはりDockerは便利ですね。次の記事(part2)では、app.pyの書き方について、公式チュートリアルから抜粋しながら基本となる部分に絞って紹介したいと思います。ありがとうございました。

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

VSCodeで手軽にpythonを勉強したい人のための環境構築(for Mac)

はじめに

「さぁ、Pythonの勉強をしよう」
と、思い立って環境を作るところから始めようと調べ始めると、
「Homebrewが…」「Pathを確認して…」「デフォルトのバージョンが…」などと
初心者の心を折ろうとする分岐がいくつも存在すると感じるのは私だけでしょうか?

色々やり方はあるかと思いますが、
私はシンプルにDockerとVisual Studio Code(以下、VSCode)の拡張機能を使って環境を作るのが
面倒なく楽なのではないかと感じましたので、それを記録として残しておきます。

もっとオススメがあるよ、という方はコメントいただければ幸いです。

インストール

それぞれ公式サイトよりダウンロード、インストールします。

Docker Desktop

Visual Studio Code

Dockerは仮想マシンを作ることが出来るサービスです。
こちらは初めて使用する際はアカウントを作る必要があります。

VSCodeのインストールはこちらの記事がとてもわかり易いです。
MacOSでVisual Studio Codeをインストールする手順

VSCodeに拡張機能を入れる

  1. VSCodeを開く。
  2. 拡張機能からRemote - Containers をインストールする。

ディレクトリとファイルを準備する

  1. 新しくフォルダを作成する
  2. .devcontainerという名前のフォルダを作る
  3. その中にdevcontainer.jsonというファイルを作る
  4. 1.のフォルダにはDockerfileとdocker-compose.yamlという2つのファイルを作成する

各種設定ファイルを書く

1. Dockerfile

pythonのバージョンを3.9に指定しています。
VSCode内でソースコードを自動整形するためのautopep8と、
コード解析ツールのpylintも一緒に入れておきます。

Dockerfile
FROM python:3.9
USER root

RUN apt-get update && apt-get -y install locales git wget unzip vim && \
    localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
ENV TZ JST-9
ENV TERM xterm

ARG DEBIAN_FRONTEND=noninteractive

RUN pip install -U pip && \
    pip install -U autopep8 && \
    pip install -U pylint

VOLUME /root/

2. docker-compose.yaml

後でVSCodeがこのファイルを見てbuildup -dをしてくれます。

docker-compose.yaml
version: "3.8"
services: 
  python3.9:
    build: 
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/root/
    working_dir: /root/
    tty: true

3. devcontainer.json

このファイルが無くても上記で出来る環境を使用できますが、
VSCodeから簡単に環境の中に入るにはこのファイルが必要です。

(※このファイルは.devcontainerフォルダの中に置いて下さい)
(Finderから隠しファイル表示を切り替えるにはcommand + shift + .(ピリオド)で可能)

devcontainer.json
{
    "name": "Python3.9",

    "dockerComposeFile": [
        "../docker-compose.yml"
    ],

    "service": "python3.9",

    "workspaceFolder": "/root/",

    "settings": { 
        "terminal.integrated.shell.linux": null
    },

    "extensions": [
        "ms-ceintl.vscode-language-pack-ja",
        "ms-python.python",
        "oderwat.indent-rainbow",
        "almenon.arepl"
    ]
}

extensionsには、以下の内容の拡張機能を自動でインストールするようにしています。
* VSCodeを日本語化する「Japanese Language Pack」

* Pythonのための「Python」

* インデントを見やすくする「indent-rainbow」

* リアルタイムでデバッグしてくれる「AREPL for python」

VSCodeから仮想環境を作成する

1. Remoteを開く

左下にある下記画像のようなアイコンを選択する

2. 「Open folder in Container」を選択する

3. 上記に自分で作成したフォルダを選択する

4. 仮想マシンの準備がはじまる


「show log」をクリックすると、実際にdocker-compose up -dなどコマンドが実行されている様子がみられるので、裏で何が行われているか確認したい方は見ると良いでしょう。

うまく環境が構築されると、下記のような画面になります。
(私はテーマやアイコンの拡張なども入れているため、見た目は一部違うことがあります)

Pythonが無事動くか確認する

せっかく導入した拡張機能のAREPLを併用して確認します。

1. .pyファイルを作ってAREPLを起動する

ここではtest.pyという名前のファイルを作りました。
作ったら、画像のように猫みたいなアイコンをクリックします。

2. ソースコードを書いてみる

何でも良いので、ソースコードを書いてみましょう。
書いている間にリアルタイムで変数やprint文が表示されているのが確認できます。

画像内ではわざと定義していない変数をprintしようとしています。
一応エディタで下線を引いて教えてくれている状態ですが、
AREPLの画面ですでにnot definedと教えてくれています。

注意点としては、あまり重たい処理にはAREPLは向かないです。
例えば上記for文のrangeが10000を超えてくると、当然ですがかなり反映が遅くなります。
その状態でrangeの数を減らしても、前の実行が終わらないと反映されません。

本当に簡単な軽いプログラムで処理内容をできるだけすぐ見たい方におすすめですが、
そうではないなら、AREPLは使用しない方が良いかもしれませんね。

3. 自動整形を使ってみる

option + shift + Fできれいに整えてくれます。

4. プログラムを実行してみる

F5でプログラムが実行できます。
が、下記のように毎回デバッグの種類を聞かれて「Python File」を選択するのも面倒です。

そこで、.vscodeという隠しフォルダに、launch.jsonというデバッグの設定ファイルを作成します。
下記の表示から「launch.jsonファイルを作成します」を選択し、「Python File」を選択すれば、自動でそのファイルを作成してくれます。

今度こそF5を押すだけで、
下部のコンソール画面に実行結果が表示されます。

おわりに

VSCodeには他にも紹介しきれないくらいデバッグに便利な機能があります。
仮想環境には何をインストールしようが壊そうが、
実環境に影響なく、簡単に同じ環境を再生できるのが魅力的ですね。
初めてPython環境を作る方でこれを読んでいる方がいらっしゃいましたら、ぜひ試してみてくださいね。

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

AWS EC2にdockerをインストールする

はじめに

AWS EC2にdockerをインストールする手順です。

インストール手順

  • Amazon Linux 2
ターミナル
# yumのアップデート
sudo yum update -y

# dockerのインストール
sudo amazon-linux-extras install docker -y

# dockerの起動
sudo service docker start

# ec2-userのセカンダリグループにdockerを追加する
# ※これによりsudoを利用せずとも、dockerコマンドが利用できるようになる
sudo usermod -a -G docker ec2-user

# 一度、ターミナルを再接続する

# インストールの確認
docker info
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

バッチファイルの置き場所を WSL2 経由でマウントして Docker コンテナを起動する方法

これは何?

バッチファイルをダブルクリックして、Docker for Windows で起動する際に、そのバッチファイルの場所を WSL2 ボリュームとしてマウントする方法を提案します。

想定読者

  • WSL2 版 docker を導入している人
  • docker 起動時に volume をマウントしたときに、性能が悪いと警告された人
  • docker 起動するときにいちいち wsl を起動するのが面倒くさい人

結論

バッチファイル名のコンテナイメージを起動する例を示します。バッチファイル名を変えると、起動するコンテナイメージが変わります。

buildpack-deps.bat
@setlocal
@set "WORK=/root/workspace"

@cd /d "%~dp0"
@set "IMG=%~n0"

@if "%~0" == "%~f0" set "pause_if_error=@if errorlevel 1 pause"

@for %%i in ( "%CD%" ) do @set "WSL2CD=%%~di"
@for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do @call set "WSL2CD=%%WSL2CD:%%~i=%%~i%%"
@for %%i in ( "%CD%" ) do @call set "WSL2CD=%%WSL2CD:~0,-1%%%%~pnxi"
@set "WSL2CD=/mnt/%WSL2CD:\=/%"

wsl -e docker run -it --rm -w "%WORK%" -v "%WSL2CD%:%WORK%" %IMG% %*
%pause_if_error%
@exit /b %errorlevel%

マウントポイントは @set "WORK=/root/workspace" に直書きなので、適宜書き換えてください。
image を固定する場合、 @set "IMG=%~n0" を書き換えてください。
wsl の distro を指定していませんので、指定したい方は適当に wsl の option を追加してください。

確認環境

Windows10 1909
Docker version 19.03.13, build 4484c46d9d

解説

docker を起動する際、 wsl コマンドを経由します。
ボリュームは wsl 上の path を指定します。
WSL2CD の操作をごにょごにょやっているのは、 windows path から WSL のパスに変換する処理です。

これで、警告が消えてスッキリ!

参考

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

バッチファイルの置き場所を WSL2 経由でマウントて Docker コンテナを起動する方法

これは何?

バッチファイルをダブルクリックして、Docker for Windows で起動する際に、そのバッチファイルの場所を WSL2 ボリュームとしてマウントする方法を提案します。

想定読者

  • WSL2 版 docker を導入している人
  • docker 起動時に volume をマウントしたときに、性能が悪いと警告された人
  • docker 起動するときにいちいち wsl を起動するのが面倒くさい人

結論

バッチファイル名のコンテナイメージを起動する例を示します。バッチファイル名を変えると、起動するコンテナイメージが変わります。

buildpack-deps.bat
@setlocal
@set "WORK=/root/workspace"

@cd /d "%~dp0"
@set "IMG=%~n0"

@if "%~0" == "%~f0" set pause=pause

@for %%i in ( "%CD%" ) do @set "WSL2CD=%%~di"
@for %%i in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do @call set "WSL2CD=%%WSL2CD:%%~i=%%~i%%"
@for %%i in ( "%CD%" ) do @call set "WSL2CD=%%WSL2CD:~0,-1%%%%~pnxi"
@set "WSL2CD=/mnt/%WSL2CD:\=/%"

wsl -e docker run -it --rm -w "%WORK%" -v "%WSL2CD%:%WORK%" %IMG% %*
@if errorlevel 1 (
  %pause%
  exit /b %errorlevel%
)
@exit /b 0

マウントポイントは @set "WORK=/root/workspace" に直書きなので、適宜書き換えてください。
image を固定する場合、 @set "IMG=%~n0" を書き換えてください。
wsl の distro を指定していませんので、指定したい方は適当に wsl の option を追加してください。

確認環境

Windows10 1909
Docker version 19.03.13, build 4484c46d9d

解説

docker を起動する際、 wsl コマンドを経由します。
ボリュームは wsl 上の path を指定します。
WSL2CD の操作をごにょごにょやっているのは、 windows path から WSL のパスに変換する処理です。

これで、警告が消えてスッキリ!

参考

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