プロキシ環境下でdockerコンテナを使用する方法

概要

プロキシ環境下でdockerコンテナを使用する際、プロキシの設定が正しくできていなくてコンテナ外と通信できないというケースが多々ある。
そのため、今回はプロキシ環境下でdockerコンテナを使用するための設定を紹介する。

方法①:config.jsonを使用する

やり方としてはコンテナにプロキシの環境変数設定をするだけなのだが、やりやすい方法として2つある。
まず1つ目としてconfig.jsonを使用する方法を紹介する。


~/.docker/config.jsonにファイルを作成し、ファイルに以下の内容を追記してコンテナ作成するだけ。

{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://username:password@proxy.com:8089",
     "httpsProxy": "https://username:password@proxy.com:8089",
     "noProxy": "example1.com"
   }
 }
}

こうすることでdockerがコンテナ起動時に自動でファイル内容を参照し環境変数を反映してくれる。

<補足>

  • httpProxyとhttpsProxyは使用するプロキシサーバーのアドレスとポートを指定する。
  • @マークの前は各自の認証するためのユーザー名とパスワードを設定する。
  • プロキシサーバーを介したくないホストについてはnoProxyの方に追記する。

方法②:docker runのオプションで指定

docker runのオプションで環境変数を渡すこともできるので、config.jsonを使いたくない人はこちらでもよい。
envオプションで更新したい環境変数名を指定してあげると更新できる。

$ docker run --env HTTPS_PROXY="http://username:password@proxy.com:8089" --name container_name -it image_name

<補足>

  • container_nameについては生成させたいコンテナ名を指定する。
  • image_nameについては使用するイメージ名を指定する。


各環境変数名とオプション設定例はこちら

環境変数名 実行例
HTTP_PROXY --env HTTPS_PROXY="http://username:password@proxy.com:8089"
HTTPS_PROXY --env HTTPS_PROXY="https://username:password@proxy.com:8089"
NO_PROXY --env NO_PROXY="example1.com"

確認方法

正しく反映されたかどうか確認すべく、コンテナ内に入り環境変数をチェックする。

# コンテナ内に入る
$ docker exec -it container_name bash

# コンテナ内でenvコマンドで環境変数確認
$ env

# こんな感じで環境変数が出力される
HTTPS_PROXY=https://username:password@proxy.com:8089
HTTP_PROXY=http://username:password@proxy.com:8089
NO_PROXY=example1.com

<補足>

  • container_nameについては確認したいコンテナ名を指定する。


コンテナ内でenvコマンドを実行して、指定した環境変数(HTTPS_PROXY等)に正しく値が反映されていればOK。

dockerコンテナ内からtcp接続確認する方法

概要

以下の記事でdockerコンテナ内でpingを使用する方法を紹介したが、サーバーとクライアントのコンテナ間でtcp接続確認をしたいケースもたまにある。
powerbombkun.hatenablog.jp

pingではポート指定等できないシンプルなコマンドなので、その場合は別のコマンドを使用する必要がある。

結論

ncコマンドでクライアントコンテナからサーバにtcp接続できるか確認する。

$ nc -v 192.168.3.3  80

確認結果

上手くサーバーにtcp接続できると以下のように成功メッセージが表示される。

$ nc -v 192.168.3.3  80
Connection to 192.168.3.3 80 port [tcp/http] succeeded!

dockerイメージの保存と反映方法

dockerを使用していると、自分のPCのdockerイメージを別のPCに持って行って使用したいということがたまにあります。


イメージのファイルがどこかに保存されているはずだから、それをコピーしちゃえば良いと思いやってみると

# dockerイメージがあるフォルダに移動
$ cd /var/lib/docker/
-bash: cd: /var/lib/docker/: Permission denied

Permission deniedで怒られてしまいアクセスできません。。
ということで色々と調べてみると、dockerイメージの保存と反映はdockerコマンドでやることが分かりました。

1.dockerイメージを保存する

私のPCのイメージ一覧に登録されているbusyboxのイメージを保存する方法で説明します。

# 登録されているイメージ一覧を確認
$ docker images
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
busybox            1.34.1    7a80323521cc   11 days ago     1.24MB

# 保存したいリポジトリ名とタグを指定してsave
$ docker save busybox:1.34.1 > busybox.tar

# 保存されたか確認
$ ls
busybox.tar

ちなみに、同じリポジトリ名のイメージが複数登録されている場合、タグ指定しないと同じリポジトリ名のイメージがまとめられて保存されます。
1つだけ保存したい場合はタグ指定してください。

# 複数busyboxのリポジトリがあるとまとめられて保存される
$ docker save busybox > busybox.tar

# タグ指定してるので1つだけ保存される
$ docker save busybox:1.34.1 > busybox.tar

これでイメージの保存は完了です。

2.dockerイメージを反映する

1で保存したdockerイメージファイル(.tar)を反映したいPCにコピーして、以下のコマンドを実行してください。

# tarファイルからロードする
$ docker load < busybox.tar
084326605ab6: Loading layer [==================================================>]  1.463MB/1.463MB
Loaded image: busybox:1.34.1

# 反映できたか確認
$ docker images
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
busybox            1.34.1    7a80323521cc   11 days ago     1.24MB

これで無事にdockerイメージの保存と反映ができました。

Vue初心者の学習環境の構築方法

Vueを勉強したいが、環境構築からどうやるかさっぱり分からないVue初心者なので、まずはこの本を買って参考にやってみた。
これからはじめるVue.js 3実践入門 | 山田 祥寛 |本 | 通販 | Amazon

Vueを動かす環境について

Vueを動かす方法としては大きく分けて以下の2種類がある。

  • CDN(Content Delivery Network)経由で動かす方法
  • Node.jsやnpmをインストールして動かす方法

今回は勉強用として簡単に始めることができるCDN経由で動かす方でやってみようと思う。

CDNとは

CDNとは世界中に配置された代理サーバーのこと。
代理サーバー内にはすでにVueを動かすためのソフト類が入っており、ユーザーは近い場所にあるCDNを使いカンタンに(ソフト類のインストール不要)でVueを動かすことができる。


ただしCDNは代理サーバーなので、CDNの動作が停止している場合は動かすことができなかったり、自分のPC内で動かすのと比べてパフォーマンス面が少し劣ったりということがある。
本格的にVueでアプリを作っていくぞーってなったらNode.jsやnpmをインストールしてやった方がよさそう。

環境構築

CDN経由でやる場合環境構築手順は実際ほとんどない。
ファイルを作成して実行するだけですぐにVueを動かせる。
今回は初めてなのでブラウザで文字を表示するだけのVueプログラムを作ってみようと思う。

1.ファイル準備

とりあえず以下の2つのファイルを準備する。

  • hello.html
  • js/hello.js

2.hello.html作成

ファイルの中身に以下を記載する。
今回はただブラウザの画面に文字を表示するだけのプログラムを作る。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>Vue.js</title>
</head>
<body>
<div id="app">
  <p>{{ message }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="js/hello.js"></script>
</body>
</html>


{{ message }} と書いている箇所はマスタッシュ構文といい、Vueで定義した変数を表示させることができる便利な構文。
Vueの変数や処理は.jsファイルの方で定義する

3.hello.js作成

ファイルの中身に以下を記載する。

let app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
});

とりあえず今回は表示させるための変数(message)に「Hello Vue !」という文を入れるだけのシンプルなプログラム。

4.hello.htmlをブラウザで開く

hello.htmlをブラウザで開きこんな風に「Hello Vue !」の文字が表示されればVueは動いている。

今後はこの環境でVueの文法やコーディング方法を色々と学んでいこうと思う。

githubにsshアクセスする際パスフレーズを聞かれないようにする方法

githubにsshの公開鍵を登録してgitのコマンド(clone, pull)をすると、こんな感じでパスフレーズの入力を聞かれてしまう。

Enter passphrase for key '/c/Users/bombkun/.ssh/id_ed25519':

小さいリポジトリなら1回入力だけで終わりなのであまり気にならないが、多数のサブモジュールがある大きいリポジトリの場合だとこのパスフレーズ入力が非常に面倒だ。

何か入力せずにやれる方法がないか探していたところssh-agentを使いパスフレーズの入力を省略する方法をいくつか見つけた。
ygkb.jp

しかしこのssh-agentだが調べるとbash起動時に自動起動設定が必要だったり、logout時には自動終了するようにする必要があったりと少し面倒。


パスフレーズそもそもいらないんじゃないか?(セキュリティ的には良くないかもしれないが。。)と思い始め、キーをパスフレーズ無しで作りなおしてgithubに登録してみたところ、無事パスフレーズは聞かれなくなった。

一応キー作成手順を張っておく↓

# sshキー作成
ssh-keygen -t ed25519 -C "your_email@example.com"

# ファイルの保存場所確認
Enter file in which to save the key (C:\Users\bombkun/.ssh/id_ed25519):

# パスフレーズ入力 ⇒ ここで何も入力しない
Enter passphrase (empty for no passphrase):

# パスフレーズ再入力 ⇒ ここでも何も入力しない
Enter same passphrase again:

これで作成した公開鍵をgithubに登録すれば以降はパスフレーズは聞かれなくなる。

gitでmasterからブランチを切る方法を解説

gitを使ってチームで開発をする場合、
ほとんどの場合作業ブランチを切ってローカルで作業をすると思う。
だが、git初心者はまずコマンドもよく知らないのでブランチを切ることさえも分からないことが多い。

初心者にも分かるようにまとめてみた。

ブランチの切り方

githubを使っている場合

gitのコード管理にgithubを使用している場合は画面からカンタンにブランチが切れる。

  1. 自分のgithubアカウントでログインした後、以下の画像のmasterの部分を選択
  2. ブランチ名の入力欄が表示されるので、自分が付けたいブランチ名を入力する
  3. 最後にcreate branchと書かれている部分をクリックするとブランチが作成される


githubを使っていない場合

  1. ローカルの作業フォルダの中で以下のようにbranchコマンドでブランチ名を指定してブランチを切る
  2. 作成したローカルのブランチをリモートへpush
git branch test-branch
git push origin test-branch

切ったブランチの使い方

ローカルにmasterのソースをcloneしていない場合

リポジトリからローカルにcloneコマンドでブランチを新規に取得する。
以下のように-bのオプションでブランチ名の指定し、clone先のリポジトリをcloneできる。

git clone -b test-branch https://github.com/powerbombkun/programs.git

ローカルにmasterのソースをclone済みの場合

  1. fetchコマンドで最初にリモートの情報(ブランチ作成の情報)を取得
  2. switchのコマンドでブランチ名を指定して切り替える
git fetch
git switch test-branch


ブランチ切るだけでも色々なコマンド必要なのでgitは難しいね。

構造体をカンタンに初期化する方法

C言語やC++で構造体を使う場合、構造体の中にたくさんのが定義されすぎてて初期化が面倒という場面はないだろうか。

例えば以下のような型の構造体がある場合、
なにも考えずに普通に初期化しようとすると変数の数だけ初期化処理を書かなきゃいけない。

struct Sample 
{
    std::string name;
    int age;
    int param1;
    double param2;
};

// 構造体定義して1つずつ初期化
Sample sample;
sample.name = "";
sample.age = 0;
sample.param1 = 0;
sample.param2 = 0.0;

変数が少ないならこのやり方でも良いが、多いと面倒。

そんな時は定義と一緒に1行で初期化できちゃうこのやり方が便利。

// 構造体を定義して、一緒に中身を0初期化
Sample sample = {0};

1行で構造体の中身が全て0初期化できるのでとってもラクチン。

std::getとは何?使い方も一緒に

C++のコードを読んでいたところ以下のようなコードを目にした。

bool status = std::get<1>(datainfo);

std::getという構文自体を目にしたことが無かったので自分はこの意味が全く分からなかった。
いろいろ調べてみると、Tupleのデータを取り出す時に使う構文だということが分かったのでまとめておこうと思う。

Tupleとは

関数の引数や戻り値で複数のデータを渡したいが、
そのためにクラスや構造体を作るのはちょっと面倒だなあということがたまにある。
そのような場合にTupleを使う。
Tupleというのは複数個のデータを1つにまとめたもので、このように定義する。

std::tuple<int, double, bool> tupleData = std::tuple<int, double, bool>(1, 0.1, true);

このTupleで定義したデータを使うことで関数の引数を1つで扱える。

std::getの使い道

Tupleのデータを取り出したい場合に使うのがstd::getだ。
std::getの後ろに何番目のデータを取り出したいかを指定することで、
指定した位置のデータを取り出せる。

int firstValue = std::get<0>(tupleData); // 1つ目
double secondValue = std::get<1>(tupleData); // 2つ目
bool thirdValue = std::get<2>(tupleData); // 3つ目


ちなみに、データを更新する時もgetを使って行う。

std::get<0>(tupleData) = 2;
std::get<1>(tupleData) = 0.2;
std::get<2>(tupleData) = false;

getして更新するのは少し変な感じをするが、getで変数の参照を取得しそこに書き込むと考えると分かりやすい。

gitのよく使うコマンドまとめ(随時追加)

バージョン管理ツールgitでよく使うコマンドをまとめておく。

clone関連

  • リモートリポジトリをローカルにclone
git clone https://github.com/***/***.git
  • ローカルリポジトリ名を指定してリモートリポジトリをclone
git clone https://github.com/***/***.git フォルダ名

commit関連

  • 変更したファイル・フォルダをcommit対象として追加
git add file1 folder1
  • ローカルのファイル・フォルダの変更状態を確認する
git status
  • addしたファイル・フォルダをcommitする
git commit -m "コミットログ"
  • commitしたログを確認する
git log
  • commitした内容をリモートリポジトリへpushする
git push origin ブランチ名

今いるブランチのリモートリポジトリにpushしたい場合はブランチ名をHEADにしてもできる

  • 現在のフォルダ以下の全ての変更をコミットする
git commit .
  • ローカルの変更を元に戻す
git restore ファイルパス

サブモジュール関連

  • サブモジュールのソースを含めてリモートリポジトリをclone
git clone --recursive https://github.com/***/***.git
  • --recursiveを忘れてcloneしてしまったが、やっぱりサブモジュールのソースをアップデートしたい
git submodule update --init
  • 特定のサブモジュールをアップデートする
git submodule update --remote サブモジュールのリポジトリパス
  • 全てのサブモジュールを強制的にアップデートする
git submodule foreach git pull origin master

diff関連

  • ローカルリポジトリの全ての変更を確認する
git diff
  • ローカルリポジトリの変更があるファイル名だけを確認する
git diff --name-only
  • コミット同士のdiffを確認する
git diff 変更前のSHA..変更後のSHA

ブランチ関連

  • ブランチ一覧を表示する
git branch
  • ローカルリポジトリを他のブランチに切り替える
git switch ブランチ名
  • リモートのブランチリポジトリをcloneする
git clone -b ブランチ名  https://github.com/***/***.git

std::bindを使うと関数の引数を自由にコントロールできる

相変わらずC++の勉強を続けているが、本日新たにstd::bindというものを目にした。
昔はなかった気がしたので調べてみるとC++11で追加された機能らしい。

std::bindとは

一言でカンタンに言うと関数の引数を束縛する機能。
例えば引数がA,B,Cと3つあるような関数でもstd::bindをすることで、引数が1つだけの関数として呼び出すことができるようになる。

コードとしてはこんな感じ

#include <iostream>
#include <functional>

void test_function(int x, int y, int z)
{
        std::cout << "x:" << x << " y:" << y << " z:" << z << std::endl;
}

int main()
{
    test_function(1, 2, 3); // bindしないとデフォルト3つの引数指定が必要
    // 出力 ⇒ x:1 y:2 z:3     

    auto binded_func = std::bind(test_function, 1, 2, 3);
    binded_func(); // bindしたので引数指定不要
    // 出力 ⇒ x:1 y:2 z:3     

    return 0;
}

std::bindが無い場合だと以下のようにラップした関数を用意して使う等の手間が必要だったが、これが不要なのでラク

static void test_function(int x, int y, int z)
{
        std::cout << "x:" << x << " y:" << y << " z:" << z << std::endl;
}

// C++11以前はわざわざラップ関数を作らないと外から使えなかった
static void wrapped_test_function()
{
    test_function(1, 2, 3);
}

引数の順番変更や部分指定するのもカンタン

引数の省略以外にも、引数の順番変更や一部だけ指定なんかもできる。
std::placeholdersというのがあるのでこれを使用する。

部分省略の場合はこんな感じ

int main()
{
    auto binded_func = std::bind(test_function, std::placeholders::_1,
                                        2,
                                        3);
    binded_func(1); // 第1引数のみ指定、他は固定
    // 出力 ⇒ x:1 y:2 z:3

    return 0;
}

順番入れ替えの場合はこんな感じ。
std::placeholdersの後の数字が引数の何番目かに対応している。

int main()
{
    auto binded_func = std::bind(test_function, std::placeholders::_3,
                                        std::placeholders::_2,
                                        std::placeholders::_1);
    binded_func(1, 2, 3); // test_functionの第1引数が3、第2引数が2、第3引数が1
    // 出力 ⇒ x:3 y:2 z:1

    return 0;
}

クラスのメンバ関数もbindできる

bind対象にできるのはただの関数だけではなく、クラスのメンバ関数も対象にできる。
メンバ関数を指定する場合は、std::bindの2つ目の引数にインスタンスを指定する必要がある。

#include <iostream>
#include <functional>

class Hoge 
{
    public:
        void Display(int x) 
        {
            std::cout << "x:" << x << std::endl;
        }
};

int main()
{
    Hoge hoge;
    auto binded_func = std::bind(&Hoge::Display, hoge, 1); // 2つ目の引数はインスタンスを指定
    binded_func();
    // 出力 ⇒ x:1

    return 0;
}

補足

どうでもよいことだが、g++の場合だとstd::placeholdersの最大は29だった。
30個以上placeholdersで指定はできないらしい。
まぁそんな関数ふつうは無いと思うが。。