20190310のdockerに関する記事は7件です。

docker for macのttyにアクセスする新しい方法

いつのまにかdocker for macのttyの場所が変わったようで、以下のようにするとokです

screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Buildkit の Goのコードを読んで Dockerfile 抽象構文木から LLB を生成するフローを覗いてみよう!!

こんにちはpo3rinです。最近趣味でmody project の buildkit の実装をぼーっと眺めてます。

前回の記事で Dockerfile の parser を使い、Dockerfie の抽象構文木の構造を確認しました。https://qiita.com/po3rin/items/a3934f47b5e390acfdfd

更に暇なので、Dockerfile の AST がどのように LLB に変換されているかを大雑把に探ったので記事にしました。執筆時 mody/buildkit のバージョンはv0.3.3です。

LLBとは

Docker 18.09から BuildKit が正式に統合され、Dockerfileのビルドをローレベルの中間ビルドフォーマット(LLB:Low-Level intermediate build format)を介して行われるようになりました。LLBはDAG構造(上の画像のような非循環な構造)を取ることにより、ステージごとの依存を解決し、並列実行可能な形で記述可能です。これにより、BuildKitを使ったdocker build は並列実行を可能にし、従来よりもビルドを高速化しています。

参考:https://www.publickey1.jp/blog/18/docker_engine_1809buildkit9.html

Perserがどこで使われているのか探す

まず、ASTの確認で使った mody/buildkit/frontend/dockerfile/parser/parser.goparser.Parse 関数を呼び出している部分を検索してみましょう。そうすると下記がヒットします。

buildkit/frontend/dockerfile/parser/dumper/main.go
buildkit/frontend/dockerfile/instructions/parse_test.go
buildkit/frontend/dockerfile/instructions/parse_test.go
buildkit/frontend/dockerfile/dockerfile2llb/convert.go

この中で明らかにbuildkit/frontend/dockerfile/dockerfile2llb/convert.goだけが匂います。コードを見ると下記の関数が呼び出していました。

func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error){
    // ...
    dockerfile, err := parser.Parse(bytes.NewReader(dt))
    if err != nil {
        return nil, nil, err
    }
    // ...
}

Dockerfile から LLB(Low-Level intermediate build format) を生成するドンピシャの関数発見です。引数の dt は parser.Parse の引数に使うところから推察して Dockerfile のバイト列を渡しているのでしょう。opt は ConvertOpt という名前から LLB に Convert するときの Option を渡せるそうです。

DockerfileのASTがLLBになるフローを読む

それでは前回確認した Dockerfile の AST が使われているコードをみてみましょう。dockerfile.AST をさらに Parse している箇所があります。

func Dockerfile2LLB(ctx context.Context, dt []byte, opt ConvertOpt) (*llb.State, *Image, error){
    // ...
    stages, metaArgs, err := instructions.Parse(dockerfile.AST)
    if err != nil {
        return nil, nil, err
    }
    // ...
}

何やら AST から stages & metaArgs という物を手に入れています。これはなんでしょうか。ローカルで確認してみます。import で多分ハマるので mody/buildkit をクローンしてきて適当な場所にディレクトリを切るとすんなり行きます。

package main

import (
    "os"

    "github.com/kr/pretty"
    "github.com/moby/buildkit/frontend/dockerfile/instructions"
    "github.com/moby/buildkit/frontend/dockerfile/parser"
)

func main() {
    f, _ := os.Open("./Dockerfile")
    r, _ := parser.Parse(f)

    stages, metaArgs, _ := instructions.Parse(r.AST)
    pretty.Print(stages)
    pretty.Print(metaArgs)
}

対象は下記のようなマルチステージビルドするDockerfileにしましょう。

FROM golang:1.11.1 as builder

WORKDIR /api
COPY . .
ENV GO111MODULE=on
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo .

FROM alpine:latest

RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /api .
CMD ["./server"]

実行するとstagesは下記の構造であることがわかります。

[]instructions.Stage{
    {
        Name:     "builder",
        Commands: {
            &instructions.WorkdirCommand{
                withNameAndCode: instructions.withNameAndCode{
                    code:"WORKDIR /api",
                    name:"workdir"
                },
                Path:            "/api",
            },
            &instructions.CopyCommand{
                withNameAndCode: instructions.withNameAndCode{
                    code:"COPY . .",
                    name:"copy"
                },
                SourcesAndDest:  {".", "."},
                From:            "",
                Chown:           "",
            },
            &instructions.EnvCommand{
                withNameAndCode: instructions.withNameAndCode{
                    code:"ENV GO111MODULE=on",
                    name:"env"
                },
                Env:             {
                    {Key:"GO111MODULE", Value:"on"},
                },
            },
            &instructions.RunCommand{
                withNameAndCode:       instructions.withNameAndCode{
                    code:"RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo .",
                    name:"run"
                },
                withExternalData:      instructions.withExternalData{},
                ShellDependantCmdLine: instructions.ShellDependantCmdLine{
                    CmdLine:      {"CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo ."},
                    PrependShell: true,
                },
            },
        },
        BaseName:   "golang:1.11.1",
        SourceCode: "FROM golang:1.11.1 as builder",
        Platform:   "",
    },
    {
        Name:     "",
        Commands: {
            &instructions.RunCommand{
                withNameAndCode:       instructions.withNameAndCode{
                    code:"RUN apk --no-cache add ca-certificates",
                    name:"run"
                 },
                withExternalData:      instructions.withExternalData{},
                ShellDependantCmdLine: instructions.ShellDependantCmdLine{
                    CmdLine:      {"apk --no-cache add ca-certificates"},
                    PrependShell: true,
                },
            },
            &instructions.WorkdirCommand{
                withNameAndCode: instructions.withNameAndCode{
                    code:"WORKDIR /app",
                    name:"workdir"
                },
                Path:            "/app",
            },
            &instructions.CopyCommand{
                withNameAndCode: instructions.withNameAndCode{
                    code:"COPY --from=builder /api .",
                    name:"copy"
                },
                SourcesAndDest:  {"/api", "."},
                From:            "builder",
                Chown:           "",
            },
            &instructions.CmdCommand{
                withNameAndCode:       instructions.withNameAndCode{
                    code:"CMD [\"./server\"]",
                    name:"cmd"
                },
                ShellDependantCmdLine: instructions.ShellDependantCmdLine{
                    CmdLine:      {"./server"},
                    PrependShell: false,
                },
            },
        },
        BaseName:   "alpine:latest",
        SourceCode: "FROM alpine:latest",
        Platform:   "",
    },
}

何やらinstructions.Stage構造体が出てきた。中身を見るとASTよりもさらに進んで、Dockerfileをビルド可能なステージの集まりに解析している。今回はマルチステージビルドを行うDockerfileなのでlen(instructions.Stage)==2であることがわかる。そしてinstructions.Stageの中ではコマンド種類ごとに解析されている。

では更に深ぼるためにinstructions.Perserのコードを読んでみよう。

// Parse a Dockerfile into a collection of buildable stages.
// metaArgs is a collection of ARG instructions that occur before the first FROM.
func Parse(ast *parser.Node) (stages []Stage, metaArgs []ArgCommand, err error) {
    for _, n := range ast.Children {
        cmd, err := ParseInstruction(n)
        if err != nil {
            return nil, nil, &parseError{inner: err, node: n}
        }
        if len(stages) == 0 {
            // meta arg case
            if a, isArg := cmd.(*ArgCommand); isArg {
                metaArgs = append(metaArgs, *a)
                continue
            }
        }
        switch c := cmd.(type) {
        case *Stage:
            stages = append(stages, *c)
        case Command:
            stage, err := CurrentStage(stages)
            if err != nil {
                return nil, nil, err
            }
            stage.AddCommand(c)
        default:
            return nil, nil, errors.Errorf("%T is not a command type", cmd)
        }

    }
    return stages, metaArgs, nil
}

Children Nodeの数だけforで回している。そして、switch文でそのNodeがstageに関するものなのかcommandに関するものなのかを分けている。stageなら[]instructions.Stageに追加し、commandなら対象のinstructions.Stageに追加している。

commandはそれぞれ意味ごとにinstructions.CmdCommandinstructions.CopyCommandなどに大別されている。Goを書いたことがある人ならば何やらinterfaceの香りがしてきますね。buildkit/frontend/dockerfile/instructions/commands.goを見るとやはりありました。

// Command is implemented by every command present in a dockerfile
type Command interface {
    Name() string
}

これがCommandを表現するinterfaceですね。予想通りcommandの識別子を返します。識別子はbuildkit/frontend/dockerfile/command/command.goにあります。つまりこれがDockerfileで使えるコマンドの全てです。

// Define constants for the command strings
const (
    Add         = "add"
    Arg         = "arg"
    Cmd         = "cmd"
    Copy        = "copy"
    Entrypoint  = "entrypoint"
    Env         = "env"
    Expose      = "expose"
    From        = "from"
    Healthcheck = "healthcheck"
    Label       = "label"
    Maintainer  = "maintainer"
    Onbuild     = "onbuild"
    Run         = "run"
    Shell       = "shell"
    StopSignal  = "stopsignal"
    User        = "user"
    Volume      = "volume"
    Workdir     = "workdir"
)

switch文を見ると、defaultでエラーを返しています。つまり上のcommandに当てはまらないものに対してエラーを吐いています。ASTを作る時ではなくここで検知するんですね。

LLBの中身を見る

dockerfile2llb.Dockerfile2LLB のここから先は []instructions.Stage からLLBを構築していく部分になります。dockerfile2llb.Dockerfile2LLB関数で最終的に出てくるLLBの出力をサラッと確認しましょう。

package main

import (
    "io/ioutil"

    "github.com/kr/pretty"
    "github.com/moby/buildkit/client/llb/imagemetaresolver"
    "github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb"
    "github.com/moby/buildkit/util/appcontext"
)

func main() {
    df, _ := ioutil.ReadFile("./Dockerfile")

    st, img, _ := dockerfile2llb.Dockerfile2LLB(appcontext.Context(), df, dockerfile2llb.ConvertOpt{})
    pretty.Print(st)
    pretty.Print(img)
}

出力が長いので、各自確認してみてください。st(llb.State型)はまさに欲していた LLB の定義を表し、img (dockerfile2llb.Image型) コンテナイメージの基本情報が入ります。

まとめ

dockerfile2llb.Dockerfile2LLB 関数が行なっていることを図にすると下記のようなフローになります。(ちょっとBuildable Stages から LLB までの詰めが甘いですが。。)

スクリーンショット 2019-03-10 17.43.05.png

Goは読みやすくていいですね。実は README.md の mody/buildkit の buildctl コマンドを使った example でもLLBの構造を簡単に確認できます。暇ならそちらの紹介も記事にします。

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

VSCodeをブラウザで使えるようにしたcode-serverをカスタマイズしてDockerで立てる

※対象環境はWindows10 Profesional以降

TL;DR

  • WSL ではまだ動かない
  • ネットワーク周りとSSHキー周りがめんどくさい
  • volume でマウントしたディレクトリにシンボリックリンクが張れないのでこれまためんどい

きっかけ

先日とある記事1 を読み、code-serverに興味が出ました。
ちょうど最近Windowsの開発バージョンを上げたところ、シンタックスチェック等が効かなくなってしまって、環境を変えたいなと思ってた矢先だったので環境構築してみようと思いました。

成果物

リポジトリ作りました
詳しくはこちらを見ていただけたらと思います。

予め試したこと

WSLで動かしてみる

結論から言うとだめでした。2
どうやらバイナリのパッケージ化方法に問題があるらしい?自分でビルドしてみたら動くかもしれないがそこまでの気力がなかったので待ち。
ならばDockerでやってみるかという運びに。

検証

公式のリポジトリを見るとすでにDockerでの立ち上げ方の記載がありますのでそれをベースとしてやっていきます。

こちらが公式の立ち上げ手順。

公式に記載されているDockerでの試用手順
docker run -p 127.0.0.1:8443:8443 -v "${PWD}:/root/project" codercom/code-server code-server --allow-http --no-auth

公式の方法はあくまでお試しの方法で、dockerコンテナを落とすと作業した内容が全て闇に葬り去られます。
例えば、

  • 編集していたファイル
  • 導入したソフトウェア
  • 導入した拡張機能

とか。

今回はそこを解消していこうと思います。

環境構築

code-server公式が出しているDockerイメージをベースに拡張していきます。

以下の方針3でDockerfile化します。

  • 拡張機能は vscode で導入する
  • 必要なソフトウェアは予めビルドしてイメージ化する

解説するDockerfile:

Dockerfile
FROM codercom/code-server

WORKDIR /root
# install dependency
RUN apt-get update \
 && apt-get install -y \
    libx11-xcb1 \
    libasound2 \
    curl \
    gnupg2 \
    git \
    python \
    g++ \
    gcc \
    libc6-dev \
    make \
    pkg-config \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

# install vscode
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
 && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
 && rm microsoft.gpg \
 && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
 && apt-get update \
 && apt-get install -y code \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

COPY scripts /usr/local/bin
COPY extensions.txt /root

...(中略)...

# Install vscode extensions
RUN install-extensions.sh

COPY settings.json /root/.code-server/User/settings.json

WORKDIR /root/project

CMD ["entrypoint.sh"]

ちなみに中略のところで Golang と Node を入れています。

VSCodeを入れる

VSCode を導入していきます。
ベースにしたイメージでは apt-get が使用できますので、それを使ってインストールしていきます。4

Dockerfileの一部
# install vscode
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
 && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
 && rm microsoft.gpg \
 && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
 && apt-get update \
 && apt-get install -y code \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

また、VSCode を立ち上げるのにいくつかライブラリが必要でしたので事前に入れておきます。

Dockerfileの一部
RUN apt-get update \
 && apt-get install -y \
    libx11-xcb1 \
    libasound2 \

これで code コマンドを使用する準備が整いました。
次に拡張機能のインストールをしていきます。

VSCode の拡張機能をインストールする

拡張機能のインストールはコマンド行います。

先程インストールした code コマンドで拡張機能をインストールできます。

拡張機能をインストールするコマンド
$ code --user-data-dir --extensions-dir /root/.code-server/extensions --install-extension [Extension-ID]
  • --user-data-dir は root ユーザーで code コマンドを実行するとエラーが出るため入れています。
  • --extensions-dir /root/.code-server/extensionscode-server の拡張機能のディレクトリに合わせています

Dockerfile では extension.txt に記載した拡張機能をインストールするように以下のコマンドを実行しています。管理を楽にしたいっていうちょっとしたオシャレです。

install-extensions.sh
#!/bin/sh

grep -v -e '^\s*#' -e '^\s*$' /root/extensions.txt | awk '{system("code --user-data-dir --extensions-dir /root/.code-server/extensions --install-extension "$1)}'

ちなみに extension.txt はこの様になっています。

extension.txt
# Editor View
akamud.vscode-theme-onedark
gruntfuggly.activitusbar
emmanuelbeziat.vscode-great-icons

# Edit field
shardulm94.trailing-spaces
coenraads.bracket-pair-colorizer
wayou.vscode-todo-highlight

# Input support
formulahendry.auto-close-tag
formulahendry.auto-rename-tag

# Node
dbaeumer.vscode-eslint

# Golang
ms-vscode.go

# Language pack
ms-ceintl.vscode-language-pack-ja

#
editorconfig.editorconfig
formulahendry.terminal

気になる拡張機能があればこちらからガンガン追加していきます。

テーマを反映する

このままだとテーマが反映されません。
なので設定ファイル settings.json も Dockerfile で追加します。

Dockerfileの一部
COPY settings.json /root/.code-server/User/settings.json
settings.json
{
    "workbench.iconTheme": "vscode-great-icons",
    "workbench.colorTheme": "Atom One Dark"
}

次に code-server を立ち上げるよう追加します。

code-server を立ち上げる

あとは code-server コマンドを実行すればいいだけなのですが、何もせずに docker run するだけだといくらか問題があります。

  • 不正な証明書でブラウザにブロックされる
  • パスワードをいちいち入力する必要がある

なので、code-server 公式に書いてあるものと同じオプションで立ち上げます。

ebtrypoint.sh
#!/bin/sh

code-server --allow-http --no-auth /root/project

まぁローカルで使う前提なら認証もhttpsも不要でしょう。

ちなみに code-server コマンドには以下のオプションが存在します。

code-serverのオプション
$ code-server --help
Start your own self-hosted browser-accessible VS Code

USAGE
  $ server [WORKDIR]

ARGUMENTS
  WORKDIR  [default: /root/project] Specify working dir

OPTIONS
  -d, --data-dir=data-dir
  -h, --host=host          [default: 0.0.0.0]
  -o, --open               Open in browser on startup
  -p, --port=port          [default: 8443] Port to bind on
  -v, --version            show CLI version
  --allow-http
  --cert=cert
  --cert-key=cert-key
  --help                   show CLI help
  --no-auth
  --password=password

docker-compose.yml を書いて毎回長いコマンドを打たなくて良くする

docker コマンドの長ったらしい引数を毎回実行したくないです。省略したいです。
なのでサービスは一つしかありませんが、docker-compose を使用して立ち上げます。

docker-compose.yml
version: '2'
services:
  code-server:
    build: .
    container_name: code-server
    ports:
      - "8443:8443"
    volumes:
      - "./workspace:/root/project"

プロジェクトルートとして workspace をマウントするように設定しました。

とても簡潔です。
あとは docker-compose で立ち上がります。

code-server を立ち上げる

以下のコマンドを実行します。

$ docker-compose up -d

その後、http://localhost:8443 を確認します。
ということで立ち上がりました!

image.png

課題

いくらか問題点があります。どうしようか考え中です。

  • sshキーは永続化してない。毎回設定しないと git が使えない。
    • リモートの url を https://xxx.git して逃げる?
  • ポートを 8443 しか開けてないので開発が辛い。
    • IPアドレスでつないだりして軽く調べた感じやりようはありそう。
  • volume でマウントした共有ディレクトリにシンボリックリンクが使用できない。nodeの開発で問題あり。
  • 一部右クリックでコンテキストメニュが出たりする。かなしい。

おわりに

ということでカスタマイズする方法を解説させていただきました。
dotfileチックに設定を git にまとめられそうですね。

課題等でいい案がありましたら教えていただきたいです。

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

WindowsでもLinux上で開発したい!VSCodeをブラウザで使えるようにしたcode-serverをカスタマイズしてDockerで立てる

※対象環境はWindows10 Profesional以降

TL;DR

  • WSL ではまだ動かない
  • ネットワーク周りとSSHキー周りがめんどくさい
  • volume でマウントしたディレクトリにシンボリックリンクが張れないのでこれまためんどい

きっかけ

先日とある記事1 を読み、code-serverに興味が出ました。
ちょうど最近Windowsの開発バージョンを上げたところ、シンタックスチェック等が効かなくなってしまって、環境を変えたいなと思ってた矢先だったので環境構築してみようと思いました。

成果物

リポジトリ作りました
詳しくはこちらを見ていただけたらと思います。

予め試したこと

WSLで動かしてみる

結論から言うとだめでした。2
どうやらバイナリのパッケージ化方法に問題があるらしい?自分でビルドしてみたら動くかもしれないがそこまでの気力がなかったので待ち。
ならばDockerでやってみるかという運びに。

検証

公式のリポジトリを見るとすでにDockerでの立ち上げ方の記載がありますのでそれをベースとしてやっていきます。

こちらが公式の立ち上げ手順。

公式に記載されているDockerでの試用手順
docker run -p 127.0.0.1:8443:8443 -v "${PWD}:/root/project" codercom/code-server code-server --allow-http --no-auth

公式の方法はあくまでお試しの方法で、dockerコンテナを落とすと作業した内容が全て闇に葬り去られます。
例えば、

  • 編集していたファイル
  • 導入したソフトウェア
  • 導入した拡張機能

とか。

今回はそこを解消していこうと思います。

環境構築

code-server公式が出しているDockerイメージをベースに拡張していきます。

以下の方針3でDockerfile化します。

  • 拡張機能は vscode で導入する
  • 必要なソフトウェアは予めビルドしてイメージ化する

解説するDockerfile:

Dockerfile
FROM codercom/code-server

WORKDIR /root
# install dependency
RUN apt-get update \
 && apt-get install -y \
    libx11-xcb1 \
    libasound2 \
    curl \
    gnupg2 \
    git \
    python \
    g++ \
    gcc \
    libc6-dev \
    make \
    pkg-config \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

# install vscode
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
 && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
 && rm microsoft.gpg \
 && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
 && apt-get update \
 && apt-get install -y code \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

COPY scripts /usr/local/bin
COPY extensions.txt /root

...(中略)...

# Install vscode extensions
RUN install-extensions.sh

COPY settings.json /root/.code-server/User/settings.json

WORKDIR /root/project

CMD ["entrypoint.sh"]

ちなみに中略のところで Golang と Node を入れています。

VSCodeを入れる

VSCode を導入していきます。
ベースにしたイメージでは apt-get が使用できますので、それを使ってインストールしていきます。4

Dockerfileの一部
# install vscode
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
 && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
 && rm microsoft.gpg \
 && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
 && apt-get update \
 && apt-get install -y code \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

また、VSCode を立ち上げるのにいくつかライブラリが必要でしたので事前に入れておきます。

Dockerfileの一部
RUN apt-get update \
 && apt-get install -y \
    libx11-xcb1 \
    libasound2 \

これで code コマンドを使用する準備が整いました。
次に拡張機能のインストールをしていきます。

VSCode の拡張機能をインストールする

拡張機能のインストールはコマンド行います。

先程インストールした code コマンドで拡張機能をインストールできます。

拡張機能をインストールするコマンド
$ code --user-data-dir --extensions-dir /root/.code-server/extensions --install-extension [Extension-ID]
  • --user-data-dir は root ユーザーで code コマンドを実行するとエラーが出るため入れています。
  • --extensions-dir /root/.code-server/extensionscode-server の拡張機能のディレクトリに合わせています

Dockerfile では extension.txt に記載した拡張機能をインストールするように以下のコマンドを実行しています。管理を楽にしたいっていうちょっとしたオシャレです。

install-extensions.sh
#!/bin/sh

grep -v -e '^\s*#' -e '^\s*$' /root/extensions.txt | awk '{system("code --user-data-dir --extensions-dir /root/.code-server/extensions --install-extension "$1)}'

ちなみに extension.txt はこの様になっています。

extension.txt
# Editor View
akamud.vscode-theme-onedark
gruntfuggly.activitusbar
emmanuelbeziat.vscode-great-icons

# Edit field
shardulm94.trailing-spaces
coenraads.bracket-pair-colorizer
wayou.vscode-todo-highlight

# Input support
formulahendry.auto-close-tag
formulahendry.auto-rename-tag

# Node
dbaeumer.vscode-eslint

# Golang
ms-vscode.go

# Language pack
ms-ceintl.vscode-language-pack-ja

#
editorconfig.editorconfig
formulahendry.terminal

気になる拡張機能があればこちらからガンガン追加していきます。

テーマを反映する

このままだとテーマが反映されません。
なので設定ファイル settings.json も Dockerfile で追加します。

Dockerfileの一部
COPY settings.json /root/.code-server/User/settings.json
settings.json
{
    "workbench.iconTheme": "vscode-great-icons",
    "workbench.colorTheme": "Atom One Dark"
}

次に code-server を立ち上げるよう追加します。

code-server を立ち上げる

あとは code-server コマンドを実行すればいいだけなのですが、何もせずに docker run するだけだといくらか問題があります。

  • 不正な証明書でブラウザにブロックされる
  • パスワードをいちいち入力する必要がある

なので、code-server 公式に書いてあるものと同じオプションで立ち上げます。

ebtrypoint.sh
#!/bin/sh

code-server --allow-http --no-auth /root/project

まぁローカルで使う前提なら認証もhttpsも不要でしょう。

ちなみに code-server コマンドには以下のオプションが存在します。

code-serverのオプション
$ code-server --help
Start your own self-hosted browser-accessible VS Code

USAGE
  $ server [WORKDIR]

ARGUMENTS
  WORKDIR  [default: /root/project] Specify working dir

OPTIONS
  -d, --data-dir=data-dir
  -h, --host=host          [default: 0.0.0.0]
  -o, --open               Open in browser on startup
  -p, --port=port          [default: 8443] Port to bind on
  -v, --version            show CLI version
  --allow-http
  --cert=cert
  --cert-key=cert-key
  --help                   show CLI help
  --no-auth
  --password=password

docker-compose.yml を書いて毎回長いコマンドを打たなくて良くする

docker コマンドの長ったらしい引数を毎回実行したくないです。省略したいです。
なのでサービスは一つしかありませんが、docker-compose を使用して立ち上げます。

docker-compose.yml
version: '2'
services:
  code-server:
    build: .
    container_name: code-server
    ports:
      - "8443:8443"
    volumes:
      - "./workspace:/root/project"

プロジェクトルートとして workspace をマウントするように設定しました。

とても簡潔です。
あとは docker-compose で立ち上がります。

code-server を立ち上げる

以下のコマンドを実行します。

$ docker-compose up -d

その後、http://localhost:8443 を確認します。
ということで立ち上がりました!

image.png

課題

いくらか問題点があります。どうしようか考え中です。

  • sshキーは永続化してない。毎回設定しないと git が使えない。
    • リモートの url を https://xxx.git して逃げる?
  • ポートを 8443 しか開けてないので開発が辛い。
    • IPアドレスでつないだりして軽く調べた感じやりようはありそう。
  • volume でマウントした共有ディレクトリにシンボリックリンクが使用できない。nodeの開発で問題あり。
    • 名前付きボリュームで解消できなくはない。Windowsで使うならさらにSMBか…
  • 一部右クリックでコンテキストメニュが出たりする。かなしい。
  • 言語が日本語にできなかった。
    • LANG=ja_JP.UTF-8 してもだめだった。VSCodeの言語を変えてみたがだめ、八方塞がり。

おわりに

ということでカスタマイズする方法を解説させていただきました。
dotfileチックに設定を git にまとめられそうですね。

課題等でいい案がありましたら教えていただきたいです。

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

WindowsでもLinux上でVSCodeで開発したい!code-serverをカスタマイズしてDockerで立てる

※対象環境はWindows10 Profesional以降

TL;DR

  • WSL ではまだ動かない
  • ネットワーク周りとSSHキー周りがめんどくさい
  • volume でマウントしたディレクトリにシンボリックリンクが張れないのでこれまためんどい

きっかけ

先日とある記事1 を読み、code-serverに興味が出ました。
ちょうど最近Windowsの開発バージョンを上げたところ、シンタックスチェック等が効かなくなってしまって、環境を変えたいなと思ってた矢先だったので環境構築してみようと思いました。

成果物

リポジトリ作りました
詳しくはこちらを見ていただけたらと思います。

予め試したこと

WSLで動かしてみる

結論から言うとだめでした。2
どうやらバイナリのパッケージ化方法に問題があるらしい?自分でビルドしてみたら動くかもしれないがそこまでの気力がなかったので待ち。
ならばDockerでやってみるかという運びに。

検証

公式のリポジトリを見るとすでにDockerでの立ち上げ方の記載がありますのでそれをベースとしてやっていきます。

こちらが公式の立ち上げ手順。

公式に記載されているDockerでの試用手順
docker run -p 127.0.0.1:8443:8443 -v "${PWD}:/root/project" codercom/code-server code-server --allow-http --no-auth

公式の方法はあくまでお試しの方法で、dockerコンテナを落とすと作業した内容が全て闇に葬り去られます。
例えば、

  • 編集していたファイル 【追記】ファイルにvオプションついてて問題なしです
  • 導入したソフトウェア
  • 導入した拡張機能

とか。

今回はそこを解消していこうと思います。

環境構築

code-server公式が出しているDockerイメージをベースに拡張していきます。

以下の方針3でDockerfile化します。

  • 拡張機能は vscode で導入する
  • 必要なソフトウェアは予めビルドしてイメージ化する

解説するDockerfile:

Dockerfile
FROM codercom/code-server

WORKDIR /root
# install dependency
RUN apt-get update \
 && apt-get install -y \
    libx11-xcb1 \
    libasound2 \
    curl \
    gnupg2 \
    git \
    python \
    g++ \
    gcc \
    libc6-dev \
    make \
    pkg-config \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

# install vscode
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
 && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
 && rm microsoft.gpg \
 && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
 && apt-get update \
 && apt-get install -y code \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

COPY scripts /usr/local/bin
COPY extensions.txt /root

...(中略)...

# Install vscode extensions
RUN install-extensions.sh

COPY settings.json /root/.code-server/User/settings.json

WORKDIR /root/project

CMD ["entrypoint.sh"]

ちなみに中略のところで Golang と Node を入れています。

VSCodeを入れる

VSCode を導入していきます。
ベースにしたイメージでは apt-get が使用できますので、それを使ってインストールしていきます。4

Dockerfileの一部
# install vscode
RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg \
 && install -o root -g root -m 644 microsoft.gpg /etc/apt/trusted.gpg.d/ \
 && rm microsoft.gpg \
 && sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main" > /etc/apt/sources.list.d/vscode.list' \
 && apt-get update \
 && apt-get install -y code \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*

また、VSCode を立ち上げるのにいくつかライブラリが必要でしたので事前に入れておきます。

Dockerfileの一部
RUN apt-get update \
 && apt-get install -y \
    libx11-xcb1 \
    libasound2 \

これで code コマンドを使用する準備が整いました。
次に拡張機能のインストールをしていきます。

VSCode の拡張機能をインストールする

拡張機能のインストールはコマンドで行います。

先程インストールした code コマンドで拡張機能をインストールできます。

拡張機能をインストールするコマンド
$ code --user-data-dir --extensions-dir /root/.code-server/extensions --install-extension [Extension-ID]
  • --user-data-dir は root ユーザーで code コマンドを実行するとエラーが出るため入れています。
  • --extensions-dir /root/.code-server/extensionscode-server の拡張機能のディレクトリに合わせています

Dockerfile では extension.txt に記載した拡張機能をインストールするように以下のコマンドを実行しています。管理を楽にしたいっていうちょっとしたオシャレです。

install-extensions.sh
#!/bin/sh

grep -v -e '^\s*#' -e '^\s*$' /root/extensions.txt | awk '{system("code --user-data-dir --extensions-dir /root/.code-server/extensions --install-extension "$1)}'

ちなみに extension.txt はこの様になっています。

extension.txt
# Editor View
akamud.vscode-theme-onedark
gruntfuggly.activitusbar
emmanuelbeziat.vscode-great-icons

# Edit field
shardulm94.trailing-spaces
coenraads.bracket-pair-colorizer
wayou.vscode-todo-highlight

# Input support
formulahendry.auto-close-tag
formulahendry.auto-rename-tag

# Node
dbaeumer.vscode-eslint

# Golang
ms-vscode.go

# Language pack
ms-ceintl.vscode-language-pack-ja

#
editorconfig.editorconfig
formulahendry.terminal

気になる拡張機能があればこちらからガンガン追加していきます。

テーマを反映する

このままだとテーマが反映されません。
なので設定ファイル settings.json も Dockerfile で追加します。

Dockerfileの一部
COPY settings.json /root/.code-server/User/settings.json
settings.json
{
    "workbench.iconTheme": "vscode-great-icons",
    "workbench.colorTheme": "Atom One Dark"
}

次に code-server を立ち上げるよう追加します。

code-server を立ち上げる

あとは code-server コマンドを実行すればいいだけなのですが、何もせずに docker run するだけだといくらか問題があります。

  • 不正な証明書でブラウザにブロックされる
  • パスワードをいちいち入力する必要がある

なので、code-server 公式に書いてあるものと同じオプションで立ち上げます。

ebtrypoint.sh
#!/bin/sh

code-server --allow-http --no-auth /root/project

まぁローカルで使う前提なら認証もhttpsも不要でしょう。

ちなみに code-server コマンドには以下のオプションが存在します。

code-serverのオプション
$ code-server --help
Start your own self-hosted browser-accessible VS Code

USAGE
  $ server [WORKDIR]

ARGUMENTS
  WORKDIR  [default: /root/project] Specify working dir

OPTIONS
  -d, --data-dir=data-dir
  -h, --host=host          [default: 0.0.0.0]
  -o, --open               Open in browser on startup
  -p, --port=port          [default: 8443] Port to bind on
  -v, --version            show CLI version
  --allow-http
  --cert=cert
  --cert-key=cert-key
  --help                   show CLI help
  --no-auth
  --password=password

docker-compose.yml を書いて毎回長いコマンドを打たなくて良くする

docker コマンドの長ったらしい引数を毎回実行したくないです。省略したいです。
なのでサービスは一つしかありませんが、docker-compose を使用して立ち上げます。

docker-compose.yml
version: '2'
services:
  code-server:
    build: .
    container_name: code-server
    ports:
      - "8443:8443"
    volumes:
      - "./workspace:/root/project"

プロジェクトルートとして workspace をマウントするように設定しました。

とても簡潔です。
あとは docker-compose で立ち上がります。

code-server を立ち上げる

以下のコマンドを実行します。

$ docker-compose up -d

その後、http://localhost:8443 を確認します。
ということで立ち上がりました!

image.png

課題

いくらか問題点があります。どうしようか考え中です。

  • sshキーは永続化してない。毎回設定しないと git が使えない。
    • リモートの url を https://xxx.git して逃げる?
  • ポートを 8443 しか開けてないので開発が辛い。
    • IPアドレスでつないだりして軽く調べた感じやりようはありそう。
  • volume でマウントした共有ディレクトリにシンボリックリンクが使用できない。nodeの開発で問題あり。
    • 名前付きボリュームで解消できなくはない。Windowsで使うならさらにSMBか…
  • 一部右クリックでコンテキストメニュが出たりする。かなしい。
  • 言語が日本語にできなかった。
    • LANG=ja_JP.UTF-8 してもだめだった。VSCodeの言語を変えてみたがだめ、八方塞がり。

おわりに

ということでカスタマイズする方法を解説させていただきました。
dotfileチックに設定を git にまとめられそうですね。

課題等でいい案がありましたら教えていただきたいです。

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

Azure Kuberenetes Serviceを使う

はじめに

諸事情でGKEで動かしていたアプリケーションをAKSに移行しなければなくなったので、やりかたをまとめました。
せっかくなのでACRとも連携させます。

環境:Windows 10 Pro, 64bit

環境準備

  1. VS Codeインストール
    • 別にVS Codeでなくてもいいんだけど、ms製品のほうが相性がよさそうな気がして
    • VS Code
  2. VS Code 拡張機能のインストール
    • [ctrl] + [shift] + [x]でコンテナ開発用の便利な拡張機能をインストール
    • docker
      • cap1.PNG
    • kubernetes
      • cap2.PNG
  3. Azure CLIコマンドのインストール(WSL Ubuntu)
    • Azureサービスをコマンドから実行するためのツールをインストール
$ sudo apt-get install apt-transport-https lsb-release software-properties-common -y
$ AZ_REPO=$(lsb_release -cs)
$ echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ $AZ_REPO main" | \
    sudo tee /etc/apt/sources.list.d/azure-cli.list
$ curl -OL http://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb`
$ sudo apt update
$ sudo apt install azure-cli

参考:WSLでAzure CLIを試してみる
4. kubectlコマンドのインストール(WSL Ubuntu)
- バイナリをダウンロードして保存して環境変数に追加する

$ sudo apt-get update && sudo apt-get install -y apt-transport-https
$ curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo touch /etc/apt/sources.list.d/kubernetes.list
$ echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee --a /etc/apt/sources.list.d/kubernetes.list
$ sudo apt-get update
$ sudo apt-get install -y kubectl
  • バージョン確認
$ kubectl version

Azure Container Registryを使ったコンテナイメージのビルドと公開

  • ACR名設定
$ ACR_NAME=sampleYuxzuxRepositry
  • ACR名チェック
    • ACR名は世界でユニークじゃないといけないのでチェックする
$ az acr check-name -n $ACR_NAME
  • リソースグループ名設定
$ ACR_RES_GROUP=$ACR_NAME
  • リソースグループ作成
$ az group create --resource-group $ACR_RES_GROUP --location japaneast
  • ACRレジストリ作成
$ az acr create --resource-group $ACR_RES_GROUP --name $ACR_NAME --sku Standard --location japaneast
  • イメージのビルド
$ az acr build --registry $ACR_NAME --image yuxzux:v1.0 .
  • イメージの確認
$ az acr repository show-tags -n $ACR_NAME --repository yuxzux
  • ACR_IDを取得して環境変数に設定
$ ACR_ID=$(az acr show --name $ACR_NAME --query id --output tsv)
  • サービスプリンシパル名の設定
$ SP_NAME="sample-acr-service-principal"
  • サービスプリンシパルの作成
$ SP_PASSWD=$(az ad sp create-for-rbac --name $SP_NAME --role Reader --scopes $ACR_ID --query password --output tsv)
  • サービスプリンシパルのIDをAPP_IDに設定
$ APP_ID=$(az ad sp show --id http://$SP_NAME --query appId --output tsv)
  • 確認
$ echo $APP_ID
$ echo $SP_PASSWD

Azure Kubernetes Serviceを使ったクラスター作成

  • クラスターの作成
$ AKS_CLUSTER_NAME=YuxzuxCluster
  • クラスターを作成するリソースグループの設定
$ AKS_RES_GROUP=$AKS_CLUSTER_NAME
  • リソースグループの作成
$ az group create --resource-group $AKS_RES_GROUP --location japaneast
  • クラスターの作成(Cloud Shell)
$ az aks create \
    --name $AKS_CLUSTER_NAME \
    --resource-group $AKS_RES_GROUP \
    --node-count 3 \
    --node-vm-size Standard_DS1_v2 \
    --generate-ssh-keys \
    --service-principal $APP_ID \
    --client-secret $SP_PASSWD
  • 認証情報の取得
$ az aks get-credentials --admin --resource-group $AKS_RES_GROUP --name $AKS_CLUSTER_NAME

以上。kubectlコマンドでいろいろできます。

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

Dockerのimageの名称を変更する手順

やりたいこと

"jupyter-image"を"jupyter" に変更したい。

$ docker image ls | grep jupyter
jupyter-image       latest              3fc840b49a0f        3 minutes ago       601MB

手順

# imageをコピーする。
$ docker tag 3fc840b49a0f jupyter
$ docker image ls | grep jupyter
jupyter-image       latest              3fc840b49a0f        5 minutes ago       601MB
jupyter             latest              3fc840b49a0f        5 minutes ago       601MB

# コピー元のimageを削除
$  docker rmi jupyter-image
Untagged: jupyter-image:latest

# 変更できた!
$ docker image ls | grep jupyter
jupyter             latest              3fc840b49a0f        5 minutes ago       601MB
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む