docker
TinkerBoard

[メモ] Docker on ASUS Tinker Board

概要

TinkerBoardもTinkerOS 2.0.3(Beta)にて、docker対応とのことで、インストールと簡単なテスト。
# リリースノートの > 22. Enable Docker support.

  • (追記) docker-compose の導入

    linaro@tinkerboard:~/compose$ docker-compose version
    docker-compose version 1.17.0-rc1, build 2a0dd14
    docker-py version: 2.5.1
    CPython version: 2.7.13
    OpenSSL version: OpenSSL 1.0.1t  3 May 2016
    linaro@tinkerboard:~/compose$ 
    

環境

手順

  1. TinkerOS 2.0.3(beta)をmicroSDを焼いて、起動して、適当に初期設定を済ませる。
    いつものツールで、いつも通りに。

  2. dockerのインストール
    curl -sSL https://get.docker.com/ | sh

    実行例
    linaro@tinkerboard:~$ curl -sSL https://get.docker.com/ | sh
    # Executing docker install script, commit: 49ee7c1
    + sudo -E sh -c apt-get update -qq >/dev/null
    + sudo -E sh -c apt-get install -y -qq apt-transport-https ca-certificates curl software-properties-common >/dev/null
    + sudo -E sh -c curl -fsSL "https://download.docker.com/linux/debian/gpg" | apt-key add -qq - >/dev/null
    Warning: apt-key output should not be parsed (stdout is not a terminal)
    + sudo -E sh -c echo "deb [arch=armhf] https://download.docker.com/linux/debian stretch edge" > /etc/apt/sources.list.d/docker.list
    + [ debian = debian ]
    + [ stretch = wheezy ]
    + sudo -E sh -c apt-get update -qq >/dev/null
    + sudo -E sh -c apt-get install -y -qq --no-install-recommends docker-ce >/dev/null
    + sudo -E sh -c docker version
    Client:
     Version:      17.10.0-ce
     API version:  1.33
     Go version:   go1.8.3
     Git commit:   f4ffd25
     Built:        Tue Oct 17 19:19:19 2017
     OS/Arch:      linux/arm
    
    Server:
     Version:      17.10.0-ce
     API version:  1.33 (minimum version 1.12)
     Go version:   go1.8.3
     Git commit:   f4ffd25
     Built:        Tue Oct 17 19:13:06 2017
     OS/Arch:      linux/arm
     Experimental: false
    If you would like to use Docker as a non-root user, you should now consider
    adding your user to the "docker" group with something like:
    
      sudo usermod -aG docker linaro
    
    Remember that you will have to log out and back in for this to take effect!
    
    WARNING: Adding a user to the "docker" group will grant the ability to run
             containers which can be used to obtain root privileges on the
             docker host.
             Refer to https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface
             for more information.
    linaro@tinkerboard:~$ 
    
  3. docker実行
    docker-hubのarm32v7 あたりとか、らずぱいのDockerでおなじみのresinが使えそう。

    1. hello-world
      sudo docker run arm32v7/hello-world

      実行例
      linaro@tinkerboard:~$ sudo docker run arm32v7/hello-world
      Unable to find image 'arm32v7/hello-world:latest' locally
      latest: Pulling from arm32v7/hello-world
      e70c9dbed03f: Pull complete 
      Digest: sha256:2e1917f5e14207289d534382d91834610860d3616dfd36406625f76ff20394fc
      Status: Downloaded newer image for arm32v7/hello-world:latest
      
      Hello from Docker!
      This message shows that your installation appears to be working correctly.
      
      To generate this message, Docker took the following steps:
       1. The Docker client contacted the Docker daemon.
       2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
       3. The Docker daemon created a new container from that image which runs the
          executable that produces the output you are currently reading.
       4. The Docker daemon streamed that output to the Docker client, which sent it
          to your terminal.
      
      To try something more ambitious, you can run an Ubuntu container with:
       $ docker run -it ubuntu bash
      
      Share images, automate workflows, and more with a free Docker ID:
       https://cloud.docker.com/
      
      For more examples and ideas, visit:
       https://docs.docker.com/engine/userguide/
      
      linaro@tinkerboard:~$ 
      
    2. arm32v7:nextcloud
      docker run -d -p 8080:80 arm32v7/nextcloud # 一番簡単な例なので、複雑な設定は、サイトを参考に.

      実行例
      linaro@tinkerboard:~$ sudo docker run -d -p 8080:80 arm32v7/nextcloud
      Unable to find image 'arm32v7/nextcloud:latest' locally
      latest: Pulling from arm32v7/nextcloud
      e52c47bf5ccb: Pull complete 
      be530d54777d: Pull complete 
      c4780c6a3912: Pull complete 
      fc2b072a68b1: Pull complete 
      58b5aa77f567: Pull complete 
      6631b21dd713: Pull complete 
      6ee4dfbed472: Pull complete 
      6d81fa28c2f4: Pull complete 
      8ce7fe74fd86: Pull complete 
      dab442480b9e: Pull complete 
      6ff1a1dd9c25: Pull complete 
      d1ee1ba71da0: Pull complete 
      721e493a487d: Pull complete 
      f8e123eceb19: Pull complete 
      66319f6b306a: Pull complete 
      f8fbc03f971e: Pull complete 
      5f478fa227e1: Pull complete 
      8df1a85865f9: Pull complete 
      26ae2cb9ffc4: Pull complete 
      1fbbdf3b652c: Pull complete 
      eeca043b6e17: Pull complete 
      5ed336af1913: Pull complete 
      Digest: sha256:6f09454420829053a54c2a7db4cc177e7910e44495e1beda66df33231569d534
      Status: Downloaded newer image for arm32v7/nextcloud:latest
      0c57197633dae6d6fe1293349c6702049f187907dc5c05d930eb7a884c11e08a
      linaro@tinkerboard:~$ sudo docker ps 
      CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
      0c57197633da        arm32v7/nextcloud   "/entrypoint.sh ap..."   2 minutes ago       Up 2 minutes        0.0.0.0:8080->80/tcp   affectionate_brown
      linaro@tinkerboard:~$ 
      
      • ブラウザから、http://tinkerboard.local:8080/ (または、tinkerboardのIPアドレス:8080)にアクセス

      image.png

    3. resin/raspberry-pi-alpine-node

      1. node.jsで、console.log('Hello World')を実行してみる。

        こぴぺ
        echo console.log\(\'Hello World\'\) > ./helloworld.js 
        sudo docker run -it --rm --name my-helloworld -p 8080:80 -v "$PWD":/usr/src/myapp -w /usr/src/myapp resin/raspberry-pi-alpine-node node ./helloworld.js
        
        コマンドラインメモ
        -i インタラクティブ(入力を受け付ける)
        -t 仮想端末(pseudo tty)割り当て
        --rm 実行後、コンテナ削除
        -p ホストポート:コンテナポート
        -v localのフォルダ:Docker内で見えるフォルダ`
        -w ワークディレクトリ指定`
        resin/raspberry-pi-alpine-node dockerコンテナイメージ
        node コマンドライン 実行ファイル
        ./helloworld.js コマンドライン パラメータ
        
        実行例
        linaro@tinkerboard:~$ echo console.log\(\'Hello World\'\) > ./helloworld.js 
        linaro@tinkerboard:~$ # 初回はコンテナイメージのダウンロード
        linaro@tinkerboard:~$ sudo docker run -it --rm --name my-helloworld -p 8080:80 -v "$PWD":/usr/src/myapp -w /usr/src/myapp resin/raspberry-pi-alpine-node node ./helloworld.js
        Unable to find image 'resin/raspberry-pi-alpine-node:latest' locally
        latest: Pulling from resin/raspberry-pi-alpine-node
        0864efeeb5cb: Pull complete 
        3cda69762aee: Pull complete 
        d642b7b00d5b: Pull complete 
        c1045bea1d5b: Pull complete 
        898d26f016c2: Pull complete 
        7fd479dec69a: Pull complete 
        7484e08bb57b: Pull complete 
        d6fb2afd02af: Pull complete 
        525fccb10d22: Pull complete 
        69177ad2e0ab: Pull complete 
        f090ade2dc16: Pull complete 
        45dbfa64038e: Pull complete 
        03bd318dfb6a: Pull complete 
        df6cbb4c1a42: Pull complete 
        ea100a5366c3: Pull complete 
        55903c23ebae: Pull complete 
        7c4169f4502d: Pull complete 
        Digest: sha256:3b9f6a2fe855d697bc93087fdd3c94d65fca408cc0d663d53b82533c2ac150c3
        Status: Downloaded newer image for resin/raspberry-pi-alpine-node:latest
        starting version 3.2.2
        Hello World
        linaro@tinkerboard:~$ # 2回目はコンテナイメージのダウンロードなし
        linaro@tinkerboard:~$ sudo docker run -it --rm --name my-helloworld -p 8080:80 -v "$PWD":/usr/src/myapp -w /usr/src/myapp resin/raspberry-pi-alpine-node node ./helloworld.js
        starting version 3.2.2
        Hello World
        
      2. node.jsで、httpサーバ

        hello-http.js
        var http = require('http');
        
        //create a server object:
        http.createServer(function (req, res) {
          res.write('Hello World!'); //write a response to the client
          res.end(); //end the response
        }).listen(80); //the server object listens on port 80
        
        実行
        linaro@tinkerboard:~$ sudo docker run -d --rm --name my-helloworld -p 8080:80 -v "$PWD":/usr/src/myapp -w /usr/src/myapp resin/raspberry-pi-alpine-node node ./hello-http.js
        3f92a925e025b4b8f5eb811249849fae438b3eb64748120e457528ccf62b0064
        linaro@tinkerboard:~$
        

        ブラウザでアクセス
        image.png

docker-compose

  1. 導入(ビルドとインストール)
    参考: Getting docker-compose on Raspberry Pi (ARM) the easy way

    git clone https://github.com/docker/compose.git
    cd compose
    git checkout release
    sudo docker build -t docker-compose:armhf -f Dockerfile.armhf .
    sudo docker run --rm --entrypoint="script/build/linux-entrypoint" -v $(pwd)/dist:/code/dist -v $(pwd)/.git:/code/.git "docker-compose:armhf"
    #
    # 実行ファイルをコピー
    sudo cp dist/docker-compose-Linux-armv7l /usr/local/bin/docker-compose
    sudo chown root:root /usr/local/bin/docker-compose
    sudo chmod 0755 /usr/local/bin/docker-compose
    # バージョン確認
    docker-compose version
    # docker-compose bash autocompletion
    sudo curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
    source ~/.bashrc
    
    ビルド時間
    linaro@tinkerboard:~/compose$ time sudo docker build -t docker-compose:armhf -f Dockerfile.armhf .
    .
    .
    Successfully tagged docker-compose:armhf
    
    real    23m44.521s
    user    0m2.310s
    sys 0m1.270s
    linaro@tinkerboard:~/compose$ time sudo docker run --rm --entrypoint="script/build/linux-entrypoint" -v $(pwd)/dist:/code/dist -v $(pwd)/.git:/code/.git "docker-compose:armhf"
    .
    .
    30130 INFO: Building EXE from out00-EXE.toc completed successfully.
    + mv dist/docker-compose dist/docker-compose-Linux-armv7l
    + dist/docker-compose-Linux-armv7l version
    docker-compose version 1.17.0-rc1, build 2a0dd14
    docker-py version: 2.5.1
    CPython version: 2.7.13
    OpenSSL version: OpenSSL 1.0.1t  3 May 2016
    
    real    0m54.892s
    user    0m0.120s
    sys 0m0.020s
    linaro@tinkerboard:~/compose$ 
    
  2. 実行例
    参考: Get started with Docker Compose

    • app.py : webサーバをたちあげて、redisのカウントをインクリメントするのと、カウント表示させる。
    • コンテナイメージの変更
      • Dockerfile: python:3.4-alpine から arm32v7/python
      • docker-compose.yml: redis:alpine から arm32v7/redis
    • まとめたもの

      コピペ
      #base64 ./docker-composetest-arm32v7.tbz 
      
      base64 -d << EOF > ./docker-composetest-arm32v7.tbz
      QlpoOTFBWSZTWU9dDGoAAZH/tOaQAQBw5/+yfXuWjv/v/+oQAAEAAEJACEACPFC2AKnqZGJDQGjE
      0AANBoyA00aGgAA1KDDKaGjTRoNADE0BoBkAAAPUOMmTRiGmhgJoYmjTJiBkYTRpphBkwkiCCaaJ
      mhQ3qaR6TJkxDamQ0ZA0aNBpk+SOn7c/Zmz7LLvLakO7MyENWkgV8tmi+AiIQizM4xsSkiYjKkMI
      BnR4OavR1xZtQaXeLS6s2YhP6uz7VqLQDrQwiaDyb2rCYb34eXJYj73Zfg1m677akLy8uJ1JmQro
      KWOuxQ8jR4qVRgVJa6ihBYNeA+JMQHWVXnMGPPXHcMeDdIcVlqyrBJvCDFmCLExtYzh50ilI1Kx0
      Ihz+zTq6N1JToSHQyR6GdDQGhr1kCLCNKOTYOVqeaEiNF0UbxAmUBS8hhDVtdGcGZnqEcd1SmxFn
      NUIQxhBFp2GElFhEpuiuiVXV671fucGfHlVNAInRTAayD1wN/TiqAYr2+CEhOGlOGUoIs0xCCbac
      QZZAaTiBDEDgoJg00u9JEgNFSBBqAL1jowk+2gKDb9ZOc5V1VRGLbsSC2W8erN28G/oP9R0aWBmO
      OiP6vkYioc+ZbTHtxIgieml782p893bI4sBsmKij8bU6SrxCLIY/pUaEGeIXGarftGuzmNH8Rj0F
      JtlBRvvMmR62JpSiP/cjypGBQJExFRk5NgiMLKU+nJmERJE4TYM+Ya5xZUaDy8OwRRw2QvK6NtzC
      QeyeisbO4jIWykH0hCtGlh2cZnlXhdGWsJIgb9iO4eZN/GlBhSoRpK7KCiWEfeO4fCYu5D9Ji808
      NBeYGId+gQH/F3JFOFCQT10Mag==
      EOF
      
      tar xf ./docker-composetest-arm32v7.tbz ; cd composetest
      docker-compose up
      
    • http://tinkerboard.local:5000/ へアクセス
      =>Hello World! I have been seen 2 times. こんなのが表示される。

その他

  1. コンテナ・イメージの削除

    linaro@tinkerboard:~$ # コンテナのリスト
    linaro@tinkerboard:~$ sudo docker container ls -a
    CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                     PORTS               NAMES
    52cdf481e1a3        arm32v7/hello-world   "/hello"            3 minutes ago       Exited (0) 3 minutes ago                       upbeat_swartz
    linaro@tinkerboard:~$ sudo docker container ls 
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    linaro@tinkerboard:~$ sudo docker container ls -a
    CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                     PORTS               NAMES
    52cdf481e1a3        arm32v7/hello-world   "/hello"            3 minutes ago       Exited (0) 3 minutes ago                       upbeat_swartz
    linaro@tinkerboard:~$ sudo docker ps
    CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
    linaro@tinkerboard:~$ sudo docker ps -a
    CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS                     PORTS               NAMES
    52cdf481e1a3        arm32v7/hello-world   "/hello"            3 minutes ago       Exited (0) 3 minutes ago                       upbeat_swartz
    linaro@tinkerboard:~$ 
    linaro@tinkerboard:~$ # イメージのリスト
    linaro@tinkerboard:~$ sudo docker images
    REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
    arm32v7/hello-world   latest              03addcf7ee05        5 weeks ago         1.63kB
    linaro@tinkerboard:~$ sudo docker image ls
    REPOSITORY            TAG                 IMAGE ID            CREATED             SIZE
    arm32v7/hello-world   latest              03addcf7ee05        5 weeks ago         1.63kB
    linaro@tinkerboard:~$ # 
    linaro@tinkerboard:~$ sudo docker container rm 52 # コンテナ削除 IDの先頭なん文字かでいい
    52
    linaro@tinkerboard:~$ # 
    linaro@tinkerboard:~$ sudo docker image rm 03 # イメージ削除 IDの先頭なん文字かでいい
    Untagged: arm32v7/hello-world:latest
    Untagged: arm32v7/hello-world@sha256:2e1917f5e14207289d534382d91834610860d3616dfd36406625f76ff20394fc
    Deleted: sha256:03addcf7ee05d2563458ea016627df34ee8abdf114f7403157b35e72dccbb027
    Deleted: sha256:0838109e03a3ebb986c5376d83913439503cb52488f55c45636b3deab85c53d0
    linaro@tinkerboard:~$ 
    
  2. docker-compose 実行例

    実行例docker-compose
    linaro@tinkerboard:~/composetest$ docker-compose up
    Creating network "composetest_default" with the default driver
    Building web
    Step 1/5 : FROM arm32v7/python
    latest: Pulling from arm32v7/python
    e52c47bf5ccb: Pull complete
    fd486ac73440: Pull complete
    a9d2aef63d92: Pull complete
    7b3c2155fc21: Pull complete
    b5855d6ca4f6: Pull complete
    567bbec54957: Pull complete
    b2211c7fcac7: Pull complete
    879a2fc7eb62: Pull complete
    Digest: sha256:222589c0c7ddd0adb80aa2f229cf775f6e7f06a1ce154ff826030ea956f24acd
    Status: Downloaded newer image for arm32v7/python:latest
     ---> 566d57d18ebe
    Step 2/5 : ADD . /code
     ---> 0a9d17f8a6b4
    Step 3/5 : WORKDIR /code
     ---> 8c7027e4e7f4
    Step 4/5 : RUN pip install -r requirements.txt
     ---> Running in ecd61de4d19c
    Collecting flask (from -r requirements.txt (line 1))
      Downloading Flask-0.12.2-py2.py3-none-any.whl (83kB)
    Collecting redis (from -r requirements.txt (line 2))
      Downloading redis-2.10.6-py2.py3-none-any.whl (64kB)
    Collecting Jinja2>=2.4 (from flask->-r requirements.txt (line 1))
      Downloading Jinja2-2.9.6-py2.py3-none-any.whl (340kB)
    Collecting itsdangerous>=0.21 (from flask->-r requirements.txt (line 1))
      Downloading itsdangerous-0.24.tar.gz (46kB)
    Collecting click>=2.0 (from flask->-r requirements.txt (line 1))
      Downloading click-6.7-py2.py3-none-any.whl (71kB)
    Collecting Werkzeug>=0.7 (from flask->-r requirements.txt (line 1))
      Downloading Werkzeug-0.12.2-py2.py3-none-any.whl (312kB)
    Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->flask->-r requirements.txt (line 1))
      Downloading MarkupSafe-1.0.tar.gz
    Building wheels for collected packages: itsdangerous, MarkupSafe
      Running setup.py bdist_wheel for itsdangerous: started
      Running setup.py bdist_wheel for itsdangerous: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/fc/a8/66/24d655233c757e178d45dea2de22a04c6d92766abfb741129a
      Running setup.py bdist_wheel for MarkupSafe: started
      Running setup.py bdist_wheel for MarkupSafe: finished with status 'done'
      Stored in directory: /root/.cache/pip/wheels/88/a7/30/e39a54a87bcbe25308fa3ca64e8ddc75d9b3e5afa21ee32d57
    Successfully built itsdangerous MarkupSafe
    Installing collected packages: MarkupSafe, Jinja2, itsdangerous, click, Werkzeug, flask, redis
    Successfully installed Jinja2-2.9.6 MarkupSafe-1.0 Werkzeug-0.12.2 click-6.7 flask-0.12.2 itsdangerous-0.24 redis-2.10.6
     ---> b517d4a7cbcb
    Step 5/5 : CMD ["python", "app.py"]
     ---> Running in bd7a0b370057
     ---> dd3633fd1d74
    Removing intermediate container ff7f7dfc0754
    Removing intermediate container ecd61de4d19c
    Removing intermediate container bd7a0b370057
    Successfully built dd3633fd1d74
    Successfully tagged composetest_web:latest
    WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
    Pulling redis (arm32v7/redis:latest)...
    latest: Pulling from arm32v7/redis
    02620033936d: Pull complete
    7f1b8976e9d6: Pull complete
    0064aaefd3fc: Pull complete
    9f03f7e23866: Pull complete
    1d2acb4efd43: Pull complete
    7a93ff992ef2: Pull complete
    Digest: sha256:f8d2248d73de3ea641d0b5c71a75276799ef208cc027678dc1acb1c4449ef517
    Status: Downloaded newer image for arm32v7/redis:latest
    Creating composetest_redis_1 ... 
    Creating composetest_web_1 ... 
    Creating composetest_redis_1
    Creating composetest_redis_1 ... done
    Attaching to composetest_web_1, composetest_redis_1
    redis_1  | 1:C 01 Nov 23:34:22.143 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    redis_1  | 1:C 01 Nov 23:34:22.143 # Redis version=4.0.2, bits=32, commit=00000000, modified=0, pid=1, just started
    redis_1  | 1:C 01 Nov 23:34:22.143 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
    redis_1  | 1:M 01 Nov 23:34:22.147 # Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.
    redis_1  | 1:M 01 Nov 23:34:22.148 * Running mode=standalone, port=6379.
    redis_1  | 1:M 01 Nov 23:34:22.148 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    redis_1  | 1:M 01 Nov 23:34:22.148 # Server initialized
    redis_1  | 1:M 01 Nov 23:34:22.148 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
    redis_1  | 1:M 01 Nov 23:34:22.149 * Ready to accept connections
    web_1    |  * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
    web_1    |  * Restarting with stat
    web_1    |  * Debugger is active!
    web_1    |  * Debugger PIN: 697-902-755