20200225のdockerに関する記事は13件です。

tblsでデータベースのスキーマ情報をマークダウンで出力する

概要

DBのスキーマ情報をドキュメント化したいと思ったので使用したツールをメモします。

使用方法

tblsのgithubを参考。

dockerイメージの入手

$ docker pull k1low/tbls:latest

1コマンドでデータベースをドキュメント化できる手軽さ。

$ tbls doc postgres://dbuser:dbpass@hostname:5432/dbname

dockerでやる場合は以下です。

$ docker run --rm -v $PWD:/work k1low/tbls doc postgres://dbuser:dbpass@hostname:5432/dbname

筆者の場合は、mysqlなので、以下です。

$ docker run --rm -v $PWD:/work k1low/tbls doc mysql://dbuser:dbpass@hostname:3306/dbname
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

dockerコンテナ内からホストのmysqlにアクセスする

概要

こちらの記事でWindowsホストのdockerコンテナ上にpython環境を構築しました。

dockerコンテナからホストのmysqlにアクセスした時のメモです。

環境

python 3.8.1

mysqlの設定ファイル書き換え

my.cnf内のbind-addressをコメントアウトする。

[mysqld]
# bind-address = 127.0.0.1

mysqlにユーザー追加

> grant all privileges on [db_name].* to [user_name]@"[ip_address]" identified by '[password]' with grant option;
> select user,host from mysql.user;
> FLUSH PRIVILEGES;

pythonコード

mysql_demo.py
import mysql.connector as mydb


conn = mydb.connect(
    host='(ホストのIPアドレス)',
    port='3306',
    user='admin',
    password='password',
    database='sample_db'
)

conn.ping(reconnect=True)
print(conn.is_connected())
cur = conn.cursor()
cur.execute("SELECT * FROM sample_table;")
cur.close
conn.close

rows = cur.fetchall()
for row in rows:
    print(row)

参考

https://qiita.com/yoshiokaCB/items/df4ae185be7cbc4f03ac

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

【Docker】チュートリアル(Python+php)

はじめに

Dockerを勉強するにあたり、素晴らしいチュートリアル動画があったのでそれを元に自分で手を動かして見ました。リンク先の動画は英語ですので、日本語で少し補足をしながら進めていきます。初心者のため認識の誤りがあるかもしれませんので、その際はコメント頂けると幸いです。

事前にdocker、docker-composeのインストールが必要です。

元動画

Docker Compose in 12 Minutes

最終的なフォルダ構成は以下のようになります。
スクリーンショット 2020-02-25 21.50.11.png

productディレクトリにはjsonを返すAPIをpythonで用意します。
websiteディレクトリには画面を描画するphpを用意します。

product

まずはdocker_tutorial配下にproductディレクトリを作成します。

$ mkdir product

そしてシンプルなPythonコードを作成します。flaskとflask_restfulというライブラリを使用します。

api.py
from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class Product(Resource):
    def get(self):
        return{
            'products': [
                'Ice cream',
                'Chocolate',
                'Fruit'
            ]
        }

api.add_resource(Product, '/')

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

ローカル環境にpythonをインストールしている場合は、pip installなどでライブラリをインストールしますが、Dockerを使用した場合は個別にインストールする必要はありません。その代わりにコンテナ起動時に必要となるライブラリなどを以下のテキストファイルに記載するか、後述のDockerfile内にpip installのコマンドを記載します。バージョンはライブラリの公式サイトなどを参照して使用したいバージョンを記載します。

requirements.txt
Flask==0.12
flask-restful==0.3.5

次にDockerfileを作成します。
DockerfileはDocker上で動作させるコンテナの構成情報を記述するためのファイルです。

FROM python:3-onbuild
COPY . /usr/src/app
CMD ["python", "api.py"]

FROM
FROMにはベースとするDockerイメージを指定します。また「onbuild」を記載することで、Dockerfile を使って docker build をするとき、Dockerfile 内で pip install を書かなくても Dockerfile と同じディレクトリに requirements.txt があると自動的にインストールをするようになっています。

COPY
COPYにはローカルファイルをDockerイメージのどこにコピーするかを記載します。今回の場合はproductディレクトリをDocker上の/usr/src/app内にコピーします。

CMD
CMDにはコンテナ起動時に実行するコマンドを記載します。

次にdocker-compose.ymlを作成します。docker-composeには

  • Dockerイメージをビルドするための情報(使用するDockerfile、イメージ名など)
  • コンテナ起動するための情報(ホストとの共有ディレクトリ設定やポートフォワードなどの起動オプションなど)
  • 使用するDockerネットワーク

などを記載します。

docker-compose.yml
version: '3'
services:
    product-service:
        build: ./product
        volumes: 
            - ./product:/usr/src/app
        ports: 
            - 5001:80

version
docker-composeで使用するバージョンを記載します。現在はバージョン3が最新ですので、3を指定します。

services
アプリケーションを動かすための各要素をServiceと読んでいます。各サービスをネストしてこちらに記載します。今回の場合は「product-service」というサービスを起動します。

build
指定したディレクトリにあるDockerfileでコンテナを起動します。今回の場合はproductディレクトリのDockerfileでコンテナを起動します。

volumes
ローカリのディレクトをコンテナのディレクトにマウントします。今回の場合はproductディレクトリをコンテナ上の/usr/src/appディレクトリにマウントします。

ports
Dockerを立ち上げるポート番号を記載します。今回は5001番ポートで立ち上げます。

それではDockerを起動

$ docker-compose up

起動が完了したら、localhost:5001にアクセスします。
以下のような画面が表示されたら問題なく起動しています。
ここまでで、簡単にPython、Flaskの環境ができることが分かります。

スクリーンショット 2020-02-25 21.18.20.png

この状態でapi.pyを以下のように変更し、保存します。

api.py
class Product(Resource):
    def get(self):
        return{
            'products': [
                'Ice cream',
                'Chocolate',
                'Fruit',
                'Eggs'
            ]
        }

再読み込みを行うと、表示内容も更新されます。コンテナを再起動しなくてもマウントしてくれます。

スクリーンショット 2020-02-25 21.21.04.png

ここまできたらコンソール上で「control+C」を押して、dockerを一旦停止します。

website

次はdocker_tutorial配下にwebsiteというディレクトリを作成します。こちらにはphpのファイルを作成します。

http://product-serviceの結果をループして表示する処理です。
ここでいうproduct-serviceはdocker-composeに記載したサービス名が該当します。

index.php
<html>
    <head>
        <title>My Shop</title>
    </head>

    <body>
        <h1>Welcome to my shop</h1>
        <ul>
            <?php
                $json = file_get_contents('http://product-service');
                $obj = json_decode($json);

                $products = $obj->products;
                foreach($products as $product) {
                    echo "<li>$product</li>";
                }
            ?>
        </ul>
    </body>

次にdocker-compose.ymlを以下のように変更します。

docker-compose.yml
version: '3'

services:
    product-service:
        build: ./product
        volumes: 
            - ./product:/usr/src/app
        ports: 
            - 5001:80

    website:
        image: php:apache
        volumes: 
            - ./website:/var/www/html
        ports: 
            - 5000:80
        depends_on: 
            - product-service

website
servicesにwebsiteというサービスを追加します。

image
imageを記載することで、Docker Hub上に用意されている既存のイメージを使用することができます。buildとimageは同時に指定することはできません。

depends_on
サービス同士の依存関係を記載します。今回の場合、websiteが実行されるより前にproduct-serviceが実行されるようになります。docker-compose.ymlにproduct-serviceがない場合はエラーになります。

再度Dockerを起動します。

$ docker-compose up

起動が完了したらlocalhost:5000にアクセスします。
以下のような画面が表示されていれば成功です。

スクリーンショット 2020-02-25 21.38.12.png

さいごに

Dockerを使用することで、簡単にPython+phpの環境を作ることができました。私もDocker初心者のためこれからも引き続き学習していきたいと思います。

おまけ

-dをつけることでバックグラウンドでコンテナを立ち上げることができます。

$ docker-compose up -d

Starting docker_tutorial_product-service_1 ... done
Starting docker_tutorial_website_1         ... done

psコマンドで起動中のコンテナの一覧が確認できます。

$ docker ps

CONTAINER ID        IMAGE                             COMMAND                  CREATED             STATUS              PORTS                  NAMES
24de043f94d9        php:apache                        "docker-php-entrypoi…"   10 minutes ago      Up About a minute   0.0.0.0:5000->80/tcp   docker_tutorial_website_1
da62924c1154        docker_tutorial_product-service   "python api.py"          32 minutes ago      Up About a minute   0.0.0.0:5001->80/tcp   docker_tutorial_product-service_1

stopでコンテナを停止することができます。

$ docker-compose stop
Stopping docker_tutorial_website_1         ... done
Stopping docker_tutorial_product-service_1 ... done

$ docker ps
ONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

参考

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

windowsにdockerでpython環境を用意する

概要

筆者はwindowsマシンを使用しています。
pythonの実行環境を用意するにあたり、
ホストがwindows、mac、linuxとコロコロ変わるので、環境構築の手軽さや、
ホストを汚したくなかった事もありdockerを使うことにしました。

環境

windows10 pro
Hyper-Vの機能を使用出来る必要があるようです。

docker for windowsインストール

以下を参考にさせて頂きインストール
https://ops.jig-saw.com/tech-cate/docker-for-windows-install

設定ファイル記述

Dockerfile

Dockerfile
FROM python:3
USER root

RUN apt-get update
RUN apt-get -y install locales && \
    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

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

docker-compose.yml

docker-compose.yml
version: '3'
services:
  python3:
    restart: always
    build: .
    container_name: 'python3'
    working_dir: '/root/'
    tty: true
    volumes:
      - ./tmp:/root/tmp
    extra_hosts:
      - "(ホストのCOMPUTERNAME):(ホストのIPアドレス)"
    ports:
      - 3306:3306
  • volumes
    ホストのパスをコンテナにマウントします。

  • extra_hosts

ホスト名のマッピングを追加します。
コンテナの/etc/hostsに以下と記載されます。

162.242.195.82  somehost
50.31.209.229   otherhost
  • ports

(ホスト側ポート):(コンテナ側ポート)

ビルド

Dockerfile含むビルド方法

> docker-compose up -d --build

コンテナ停止

> docker-compose down

参考

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

【Docker】Unhandled exception: Drive has not been shared

$ docker-compose up -d

で「Unhandled exception: Drive has not been shared」エラーが発生した場合、以下の設定を変更することで解消します。

2020-02-25_162047.png

setting→Resources→FILE SHARING→Cドライブにチェック

画面キャプチャはDocker Desktop for windowsです。

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

Laravel on Dockerでのブロードキャスト

TL;DL

Docker環境のLaravelでのブロードキャストを実装しました:thumbsup:

Dockerを使ったLaravel環境構築

インストールするのはLaravel 6.xです。

$ mkdir broadcast
$ cd broadcast
$ composer create-project --prefer-dist laravel/laravel src
├── docker-compose.yml
├── docker
│   ├── echoserver
│   │   └── Dockerfile
│   ├── nginx
│   │   └── default.conf
│   ├── php
│   │   ├── Dockerfile
│   │   ├── cmd.sh
│   │   └── php.ini
│   └── redis
│       └── data
├── logs
└── src  # Laravelの置き場所
docker-compose.yml
version: '3'

services:
  web:
    image: nginx:1.17.8-alpine
    ports:
     - 80
    volumes:
     - ./src:/var/www:cached
     - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
     - ./logs/nginx:/var/log/nginx:cached
    depends_on:
     - php
    environment:
      VIRTUAL_HOST: localhost

  php:
    image: broadcast-php
    build: ./docker/php
    volumes:
     - ./src:/var/www:cached
     - ./logs/php:/var/log/php
     - ./docker/php/cmd.sh:/usr/local/bin/cmd.sh

  nodejs:
    image: node:13.8-alpine
    volumes:
     - ./src:/work:cached
    working_dir: /work

  echo-server:
    image: broadcast-echo-server
    build: ./docker/echoserver
    ports:
     - "6001:6001"
    command: laravel-echo-server start
    volumes:
     - ./src:/work:cached
    working_dir: /work

  redis:
    image: redis:latest
    ports:
     - "6379:6379"
    volumes:
     - "./docker/redis/data:/data"
docker/echoserver/Dockerfile
FROM node:13.8-alpine

# timezone
RUN apk add --update --no-cache --virtual build-dependencies tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo "Asia/Tokyo" > /etc/timezone && \
    apk del build-dependencies

RUN npm install -g laravel-echo-server

WORKDIR /work

CMD ["laravel-echo-server", "start"]
docker/php/Dockerfile
FROM php:7.3-fpm-alpine
COPY php.ini /usr/local/etc/php/

# lib
RUN apk add --no-cache --virtual build-dependencies gcc make autoconf libc-dev libtool \
 && apk add --no-cache --virtual zlib1g-dev libxml2-dev

# composer
COPY --from=composer /usr/bin/composer /usr/bin/composer

# php extension
RUN docker-php-ext-install xml pdo_mysql

# timezone
RUN apk add --update --no-cache --virtual build-dependencies tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo "Asia/Tokyo" > /etc/timezone && \
    apk del build-dependencies

WORKDIR /var/www
docker/php/cmd.sh
#!/bin/sh
php-fpm
docker/nginx/default.conf
server {
  listen 80;
    index index.php index.html;
    root /var/www/public;
    charset utf-8;

  location / {
    root /var/www/public;
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {

    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param HOGE $realip_remote_port;
  }
}

ビルドして、最初のdocker-compose up -dではLaravel Echo Serverは起動しません。

$ docker ps -a
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                      PORTS                               NAMES
                    nginx:1.17.8-alpine     "nginx -g 'daemon of…"   14 seconds ago      Up 12 seconds               0.0.0.0:32774->80/tcp               broadcast_web_1
                    broadcast-php           "docker-php-entrypoi…"   16 seconds ago      Up 13 seconds               9000/tcp                            broadcast_php_1
                    node:13.8-alpine        "docker-entrypoint.s…"   16 seconds ago      Exited (0) 13 seconds ago                                       broadcast_nodejs_1
                    broadcast-echo-server   "docker-entrypoint.s…"   16 seconds ago      Exited (0) 12 seconds ago                                       broadcast_echo-server_1
                    redis:latest            "docker-entrypoint.s…"   16 seconds ago      Up 13 seconds               0.0.0.0:6379->6379/tcp              broadcast_redis_1

そこで初期化コマンドを実行する必要があります。

$ docker-compose run --rm echo-server laravel-echo-server init
? Do you want to run this server in development mode? Yes
? Which port would you like to serve from? 6001
? Which database would you like to use to store presence channel members? redis
? Enter the host of your Laravel authentication server. http://localhost
? Will you be serving on http or https? http
? Do you want to generate a client ID/Key for HTTP API? No
? Do you want to setup cross domain access to the API? No
? What do you want this config to be saved as? laravel-echo-server.json
Configuration file saved. Run laravel-echo-server start to run server.

これでsrc/laravel-echo-server.jsonという設定ファイルが作られます。
この中のRedisの接続情報でRedisコンテナを指定します。

src/laravel-echo-server.json
{
    ...

    "databaseConfig": {
        "redis": {
            "host": "redis",
            "port": 6379
        },
        "sqlite": {
            "databasePath": "/database/laravel-echo-server.sqlite"
        }
    },

    ...
}

落として、再度立ち上げます。

$ docker-compose down
$ docker-compose up -d
$ docker ps -a
CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS                      PORTS                               NAMES
                    nginx:1.17.8-alpine     "nginx -g 'daemon of…"   10 seconds ago      Up 7 seconds                0.0.0.0:32775->80/tcp               broadcast_web_1
                    node:13.8-alpine        "docker-entrypoint.s…"   11 seconds ago      Exited (0) 9 seconds ago                                        broadcast_nodejs_1
                    broadcast-php           "docker-php-entrypoi…"   11 seconds ago      Up 9 seconds                9000/tcp                            broadcast_php_1
                    broadcast-echo-server   "docker-entrypoint.s…"   11 seconds ago      Up 9 seconds                0.0.0.0:6001->6001/tcp              broadcast_echo-server_1
                    redis:latest            "docker-entrypoint.s…"   11 seconds ago      Up 9 seconds                0.0.0.0:6379->6379/tcp              broadcast_redis_1

これでLaravel Echo Serverも起動しました。

http://localhost:32775/

にアクセスするとLaravelインストール直後の画面が表示されます。

スクリーンショット 2020-02-24 13.51.58.png

ブロードキャスト

ここからが本題のブロードキャストです。
以下が公式のドキュメント。

https://laravel.com/docs/6.x/broadcasting
https://readouble.com/laravel/6.x/ja/broadcasting.html

今回はRedisを使います。
ほぼほぼ公式の手順でうまくいきます(そして公式ドキュメントに載っていない設定で躓く。。)

App\Providers\BroadcastServiceProviderの登録

コメントを外します。

$ diff src/config/app.php.orig src/config/app.php
174c174
<         // App\Providers\BroadcastServiceProvider::class,
---
>         App\Providers\BroadcastServiceProvider::class,

HTMLへのCSRFトークンの追加とJSの読み込み

$ diff src/resources/views/welcome.blade.php.orig src/resources/views/welcome.blade.php
8a9,10
>         <meta name="csrf-token" content="{{ csrf_token() }}">
> 
98a101,102
> 
>         <script src="{{ mix('js/app.js') }}"></script>

Redisのクライアントライブラリのインストール

$ cd src
$ composer require predis/predis

イベントの作成

$ docker-compose exec php php artisan make:event HelloWorldEvent
Event created successfully.

イベントのbroadcastOn()でチャンネルを返すのですが、今回作るのは認証が必要ないチャンネルとします。

src/app/Events/HelloWorldEvent.php
<?php

namespace App\Events;

use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class HelloWorldEvent implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    public $message = 'Hello World!!';

    /**
     * Create a new event instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return \Illuminate\Broadcasting\Channel|array
     */
    public function broadcastOn()
    {
        return new Channel('hello-world-channel');
    }
}

イベント発行のコマンドの作成

$ docker-compose exec php php artisan make:command BroadcastHelloWorld
Console command created successfully.
src/app/Console/Commands/BroadcastHelloWorld.php
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Events\HelloWorldEvent;

class BroadcastHelloWorld extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:broadcast-hello-world';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        event(new HelloWorldEvent());
    }
}

フロントエンド

laravel-echosocket.io-clientが必要です。

$ docker-compose run --rm nodejs npm install
$ docker-compose run --rm nodejs npm install --save laravel-echo socket.io-client

なんかnpm installで警告いっぱい出た。。。
チャンネルとイベントを指定してリッスンします。

$ diff src/resources/js/app.js.orig src/resources/js/app.js
1a2,14
> 
> import Echo from 'laravel-echo';
> 
> window.io = require('socket.io-client');
> 
> window.Echo = new Echo({
>     broadcaster: 'socket.io',
>     host: window.location.hostname + ':6001'
> });
> 
> window.Echo.channel('hello-world-channel').listen('HelloWorldEvent', e => {
>     console.log(e.message);
> });

.envの変更

$ diff src/.env.orig src/.env
16c16
< BROADCAST_DRIVER=log
---
> BROADCAST_DRIVER=redis
18c18
< QUEUE_CONNECTION=sync
---
> QUEUE_CONNECTION=redis
22c22,24
< REDIS_HOST=127.0.0.1
---
> REDIS_HOST=redis
> REDIS_CLIENT=predis
> REDIS_PREFIX=""

!!重要!!
ここでRedisのprefixを空文字にすることが重要です。
これが公式ドキュメントに書かれていなくて、調べてやっと見つけました。

ブロードキャストできるか確認

$ docker-compose run --rm nodejs npm run dev
$ docker-compose exec php php artisan command:broadcast-hello-world
$ docker-compose exec php php artisan queue:work --stop-when-empty
 Processing: App\Events\HelloWorldEvent
 Processed:  App\Events\HelloWorldEvent

スクリーンショット 2020-02-24 13.56.50.png

成功しました!!
laravel-echo-server.jsonのRedisコンテナ指定の修正や、Redisのprefixの変更など、Redis周りで難しかったですが、なんとかDocker環境でブロードキャストできました:beer:

参考URL

この記事がなかったら自分は諦めてました。:pray::pray::pray:感謝:pray::pray::pray:

https://nori-life.com/laravel-broadcast-redis-socket-io/

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

【Docker】docker-compose up -d 時のエラー No container found for ○○ の対処法

コマンドdocker-compose up -dの際に、次のエラーが表示されました。

ERROR: No container found for コンテナ名

原因

起動後すぐにコンテナが落ちてしまっている

解決法

docker-compose up -dだとバックグラウンドでの起動になりエラーログがでないので、
原因を知るためにdocker-compose upでコンテナを起動する。そうすればエラーログをみることができるので何かしらの進展が期待されると思います。

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

docker-machineのデフォルトOS,shellを確認してみました

結果

ディストリビューション:Core linux
シェル:bash
ディストリビューションはコアリナックスというミニマムなものでした。
core linux

シェルは有名なbashでした。

状況

docker-machineで立ち上げた時linuxっぽいものが
動いているけどディストリビューションは何だろう?
という疑問が出てきたので確認してみました。

以下docker、docker-machineが動く前提です。

確認した手順|コマンド

Verification.sh
#verificationという名前の仮想マシンを作る
$ docker-machine create verification

#verificationにsshで入る
$ docker-machine ssh verification

#ここからはverification内でのコマンド実行
#ディストリビューションを確認するコマンド実行
$ cat /etc/issue
Core Linux

#シェルを確認
$ echo $SHELL
/bin/bash

備考

ディストリビューション(正確にはlinuxの系列)や
シェルの違いでコマンドが違ってくるので自分用備忘録として書きました。

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

WSL2+docker+PHPのWindows開発環境構築(1) WSL2編

本記事はWindows Insider Previewを使っています。
ご利用は計画的に

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪


------------------- ↓ 余談はここから ↓-------------------

関連記事
* Bash on Ubuntu on Windowsを使う(1)
* Bash on Ubuntu on Windowsを使う(2):初期設定
* Bash on Ubuntu on Windowsを使う(3):WindowsからLinuxを使う
* WSL2+docker+PHPのWindows開発環境構築(1) WSL2編
* WSL2+docker+PHPのWindows開発環境構築(2) docker編

仕事でdockerを使う機会が増えた。
なぜか知らんがMacを使わされるので大変面倒くさい。
(どこが便利なんだ?これ。)

現在の仕事はPCを持ち込みができるらしいので、
この際Windows上で開発環境を作ろうと思う。

数年前に登場したWSLというものがあって、
それについて記事も書いているが、
順調に進化してこのたびver2となる。
(リリースは令和2年5月頃)
そのときを見据えて今からPreview版を使って環境を作ってみよう。

注意
  • Preview版がStableになっても記事を書き換えたりしないのでご注意を。
  • 記事が長くなったのでdocker編は別記事で。

------------------- ↓ 本題はここから ↓-------------------

事前準備

・Windows Update

前提としてWindowsを最新にしておく。
(https://www.microsoft.com/ja-jp/software-download/windows10
(執筆時November Update 2019)

・WSLを有効にする

PowerShellを管理者モードで起動
1. 「スタート」「Windows PowerShell」「Windows PowerShell」を右クリック
2. 「管理者として実行」
2020-02-22 (3)_LI.jpg

以下のコマンドを実行

PS> dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
PS> dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestt

そしてPCを再起動! (ここ重要)

Windows Insider Previewをインストール

・Previewプログラムに参加
  1. Windows Preview Programに参加
  2. Windows Insider の設定で「開始する」を押下

2020-02-22 (7)_LI.jpg

  1. 「アカウントリンク」より自身のアカウントと紐付ける
  2. 「スロー」を選択
  3. 「再起動」
  4. 「設定」「更新とセキュリティ」「更新プログラムのチェック」を押下
  5. すべてのインストール完了後「再起動」
  6. (「Windows 10、バージョン????の機能更新プログラム」がインストールされるまで6,7を繰り返す)

2020-02-22 (9).png

・バージョンの確認

「コマンドプロンプト(またはPowerShell)」で以下のコマンドを実行

$ ver
Microsoft Windows [Version 10.0.19041.84]

数字が10.0.18917以上なら成功

WSL2のインストール

*デフォルト設定をWSL2にする

wslコマンドのデフォルト設定をWSL2になるようにしておく。
前置きが長くなったがここからが本番。

C:¥> wsl --set-default-version 2
・Linuxを取得

windows Storeで好きなLinux Distributionをダウンロードしておく
ここではベタなUbuntuを選択。
https://www.microsoft.com/ja-jp/p/ubuntu/9nblggh4msv6
(私はPengwin派)

状態確認
C:¥> wsl -l -v
  NAME   STATE  VERSION
* Ubuntu  Stopped 2

あとは普通にUbuntuを使うだけ。

C:¥> wsl
$ cat /etc/os-release
NAME="Ubuntu"
VERSION=
〜〜〜〜〜〜

さて、次はdockerだ。


------------------- ↓ 後書はここから ↓-------------------

WSL1からWSL2に変換する

すでにに手持ちのLinuxを使っていて、
WSL2に変えたいときがあるだろう。
変換する手段はあるので慌てずに。

状態の確認
C:¥> wsl -l -v
  NAME   STATE  VERSION
* WLinux  Stopped 1
  Ubuntu  Stopped 2
WSL2に変換
C:¥> wsl --set-version WLinux 2
変換中です。この処理は数分かかることがあります...

もう一度状態を確認してみる。

C:¥> wsl -l -v
  NAME   STATE  VERSION
* WLinux  Stopped 2
  Ubuntu  Stopped 2

WSL2のリセット方法

「アプリと機能」のアプリの詳細から「リセット」するのが定番だったけど、
コマンド一つでできるようになるみたい。

C:¥> wsl --unregister ubuntu

コマンドの後、「スタート」からLinuxを起動すると初期状態になっている。

ターミナルをWindows Terminalに変える

個人的におすすめしたいターミナルがWindows Termminal
https://www.microsoft.com/ja-jp/p/windows-terminal-preview/9n0dx20hk701
タブ機能が標準で付いている。

powerline対応フォントを入れる

powerlineというPython製のシェルがあるのだが、
それに対応したフォントがある。
https://github.com/powerline/fonts
install.ps1シェルをpowershellで走らせるとフォントがインストールされる

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

Dockerコンテナだけで完結するフロントエンド環境を構築するぞ!( VSCode Remote Development )

この記事は何?

VSCodeの拡張機能であるRemote Developmentを使えば、Dockerコンテナ内のソースコードを直接書き換えることができます。
これを使えば、わざわざホスト側のソースコードを書き換えてVolumeを使って、変更をコンテナ内部にマウントするなんてことをしなくて済みます。

この記事では、この拡張を使ってDockerコンテナ内だけで完結するフロントエンド( React + Webpack + TypeScript )の環境構築を行います。

詳しい解説や使い方は、以下の素晴らしい記事を参照ください。

Dockerで立ち上げた開発環境をVS Codeで開く!
VS Code Remote Development で Docker 開発環境を利用する
Visual Studio CodeのRemote DevelopmentとDockerで快適な開発環境をゲット

環境構築

Docker Imageの作成

作業がしやすいように、Dockerfileを定義して、自分好みの環境を作っておきます。こちらは、各自でカスタマイズして使いやすくしてください。もしDockerHubなどに既にイメージがある場合は、こちらの工程は不要です。

Dockerfile
# こちらのイメージには node と npm と yarn が入っています
FROM node:lts-alpine

# git と curl をインストール
# alpine版は apt-get ではなく、apkを使います
RUN apk update && apk add --virtual=module curl git

WORKDIR /usr/src/app

Dockerfileが出来たら、それを元にイメージを作成します。

$> docker build -t <任意のイメージ名前> <DockerfileのあるPATH>
example
$> docker build -t frontend .
  • -t : イメージの名前を設定します。イメージ名には大文字はダメみたいです。

処理が完了したら、ちゃんと作成されているか確認してみましょう。
例では、frontendという名前で作成しました。

$> docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE  
frontend            latest              dfcs99e             now                 106MB 
node                lts-alpine          927s12c             now                 88.1MB

ちゃんと作成されていますね。それでは次に行きましょう。

Docker Volumesの作成

volumesを作成します。理由は、volumesを設定しておかないとデータの永続化で出来ないので、誤ってDockerコンテナを削除してしまうと、作業内容が消えてしまいます。なので、volumesを作ってそこにデータを入れて永続化します。

volumesは、dockerが管理するものと任意のフォルダーに管理する方法がありますが、この記事ではdockerが管理する方法をとっています。

$> docker volume create <任意の名前>
example
$> docker volume create ReactAppVolume

こちらもちゃんと作成できているか、確認してみましょう

$> docker volume ls
DRIVER              VOLUME NAME
local               ReactAppVolume

例では、ReactAppVolumeという名前で作成しましたが、ちゃんと作成されていますね。
それでは次に行きましょう。

Docker Containerの作成

実際に作業するコンテナを作成します。こちらのコンテナは基本的にはdocker rmなどはしないようしましょう。volumesを設定してあるので、消しても大丈夫だとは思いますが。。。

$> docker run -d --name <任意の名前> -v <作成したVolume名>:<マウントしたいPATH> <イメージ名> sleep infinity
example
$> docker run -d --name SampleReactApp -v ReactAppVolume:/usr/src/app frontend sleep infinity
  • -d : バックグランドで実行
  • -v : 設定されたPATHにvolumesを設定します
  • --name : dockerコンテナに任意の名前を付けれます
  • sleep infinity : コンテナが起動したときに実行するコマンド。( これをやらないとすぐにコンテナが落ちてしまうため )

※ 本来であれば-pオプションでポート開放する必要があると思いますが、指定しなくても筆者の環境では動いたので、書いていません。
もし一通りやって、http://locahost:8080にアクセスしても404 Not Foundが出た場合は、-p 8080:8080を追加してください。

すでにVolumeがある場合

こちらは、間違ってコンテナを削除してしまった時や、コンテナを複製したい場合に使います。

$> docker run -d --name <任意のコンテナ名> --mount source=<Volume名>,target=<マウントしたいPATH> <イメージ名> sleep infinity
example
$> docker run -d --name SampleReactApp --mount source=ReactAppVolume,target=/usr/src/app frontend sleep infinity
  • --mount : volumeの内容を、指定したtargetのPATHにマウントします

作成したコンテナをVSCodeで開く

コンテナが停止してないとちゃんと動かないことがあったので、停止しておきましょう。
※ コンテナが停止していても、Remote Developmentがちゃんと検知してくれますし、開くときに勝手に起動してくれますので、大丈夫です。

$> docker stop <作成したコンテナ名> or <コンテナID>
example
$> docker stop SampleReactApp

コンテナが停止出来たら、次はVSCodeを開きます。この時Remote Developmentがインストール済みである事を想定しています。インストールをしていない人は、インストールしましょう。

※「 ワークスペースに有効にする 」だと正常に動作しないので、ちゃんと全体にインストールしましょう

そうするとアイコンが追加されて、それをクリックするとDockerコンテナ一覧が表示される画面が表示されます。

その画面が表示されたら、コンテナをVSCodeで開くアイコンがあるので、それをクリックするとコンテナをVSCodeで開くことができます。

今回の例では、イメージ名 : frontendコンテナ名 : SampleReactAppとしていますので、frontend(SampleReactApp)の項目を開きます。

vscode_remote_develop.PNG

DockerコンテナをVSCodeで開けたら後は、環境構築していくだけです。

React + Webpack + TypeScriptの環境構築

※この節のコマンドの実行は、全てDockerコンテナ内で行っています。また、この記事ではyarnを使っています。

まずは、package.jsonの作成です。

package.jsonを生成
/usr/src/app# yarn init
yarn init v1.22.0
question name (app): 
question version (1.0.0): 
question description: 
question entry point (index.js): 
question repository url: 
question author: 
question license (MIT): 
question private: 
success Saved package.json

生成されたpackage.jsonに、npm scripsを定義してましょう。

package.json
{
  "name": "app",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "set NODE_ENV=development & webpack-dev-server",
    "build": "set NODE_ENV=production & webpack"
  }
}

yarn startとコマンドを打てば、サーバが立ち上がってReactの実行結果を確認することができます。
yarn buildとコマンドを打つと、distフォルダーにビルドファイルが出力されます。

※まだこの段階では、コマンドを実行してもエラーになります。

次に、必要なモジュールのインストールを行います。

buildに必要なモジュールをインストール
/usr/src/app# yarn add -D webpack webpack-cli webpack-dev-server html-webpack-plugin clean-webpack-plugin typescript ts-loader @types/react @types/react-dom
  • -D : --save-devの略。package.jsonにdevDependenciesのモジュールとして書かれます。
  • webpack・webpack-cli : Reactをビルドするのに必要なBundler。
  • webpack-dev-server : Reactの表示内容を確認するためのサーバーを立ててくれます。
  • html-webpack-plugin : webpackで、HTMLも出力してくれるプラグイン。
  • clean-webpack-plugin : 古いビルドファイルを削除してくれるプラグイン。
  • typescript : javascriptに型を無理くり付けた言語
  • ts-loader : webpacktypescriptをコンパイルするのに使います。
  • @types/react・@types/react-dom : typescriptreact書くのに必要な型定義ファイル

次は、Reactのインストール

reactをインストール
/usr/src/app# yarn add react react-dom

次にwebpack.config.jsを定義します。こちらは必要最低限の構成になっています。

webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

const mode =
  process.env.NODE_ENV === "production" ? "production" : "development";

const isDev = process.env.NODE_ENV === "development";

const outputPath = path.resolve("src/index.tsx");

module.exports = {
  entry: outputPath,

  mode,

  devtool: isDev ? "source-map" : "none",

  target: "web",

  output: {
    path: path.resolve(__dirname, "dist"),
    publicPath: "/",
    filename: isDev ? "bundle.[hash].js" : "bundle.js"
  },

  resolve: {
    extensions: [".js", ".ts", ".tsx"],
  },

  module: {
    rules: [
      {
        test: /\.(ts|tsx)$/,
        use: "ts-loader"
      }
    ]
  },

  devServer: {
    contentBase: outputPath,
    historyApiFallback: true,
    port: 8080,
    hot: true,
    host:"0.0.0.0"
  },

  plugins: [
    new HtmlWebpackPlugin({
      title: "SampleReactApp"
    }),

    new CleanWebpackPlugin(),
  ]
};

次は、typescriptのコンパイル設定ファイルを定義。こちらは、結構適当です。

tsconfig.json
{
  "compilerOptions": {
    "outDir": "./dist/",
    "sourceMap": true,          // mapファイル出力してー
    "module": "ESNext",         // importを使えるようにしてー
    "noImplicitAny": true,      // 定義無しだと勝手にAny?ダメだ!ゆ゛る゛さ゛ん゛!
    "target": "es5",            // ES5にコンパイルしてー
    "jsx": "react",             // react使うよー
    "strict": true,             // strictモード使うよー
    "moduleResolution": "node", // node_modulesを使えるようにするよー 
    "lib": [
      "dom",   // 多分、必須
      "es2019" // 好きなesのバージョンでいいんじゃない?しらんけど。
    ]
  },
  "include": [
    "./src/**/*.ts",
    "./src/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

設定ファイルが書き終わったら、次はReactのソースコードを書いてきます。

src/index.tsx
import * as React from "react"
import { render } from "react-dom"

const App : React.SFC = () => (
  <div className="app">
    <h1>Hello React!</h1>
  </div>
)

const root = document.createElement("div")

root.id = "root"

document.body.appendChild(root)

render(<App />, root)

WebpackDevServerを立ち上げる

ここまで出来たら、yarn startを実行するとサーバーが立ち上がるので、http://localhost:8080にアクセスすると、Hello React!と書かれたページが表示されていると思います。

サーバーを起動
/usr/src/app# yarn start
yarn run v1.22.0
$ webpack-dev-server
ℹ 「wds」: Project is running at http://0.0.0.0:8080/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /usr/src/app/src/index.tsx
ℹ 「wds」: 404s will fallback to /index.html
ℹ 「wdm」: Hash: 31e9b9d394452c9a83d5
Version: webpack 4.41.6
Time: 2499ms
Built at: 2020-02-25 5:03:20
     Asset       Size  Chunks             Chunk Names
 bundle.js   1.41 MiB    main  [emitted]  main
index.html  186 bytes          [emitted]  
Entrypoint main = bundle.js

...

これで終わりです!お疲れさまでした。

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

squidでActiveDirectory連携とSSLインターセプトするProxyをdockerで手軽につくる

概要

squidによるProxyサーバで、こんなことがやりたい。

  • ActiveDirectoryのセキュリティグループを利用して、アクセスログにユーザ名を残したい。
  • セキュリティグループ毎に別のアクセス制限をかけたい。
  • アップデートサイトなどはホワイトリストにして、NTLMのSSOを回避して無認証で通したい。
  • SSLインターセプトして、HTTPSでもFQDN以降のフルパスでアクセス制限したい。

Screenshot from Gyazo

アクセス条件は次のとおり

ユーザ種別 ホワイトリスト イントラサイト 特例サイト 一般サイト ブラックリスト
システムユーザ × × × ×
通常ユーザ × × ×
一部許可ユーザ × ×
全許可ユーザ ×

検証環境

機器など

  • CentOS8(8.1.1911)
  • squid(4.4)
  • Windows Servr 2019
  • Docker(19.03.5)

その他のパラメータ

以降の作業内容では、以下のパラメータにあわせて説明をしています。
カスタマイズする場合には、適宜修正をしてください。

ドメイン名

ADドメイン名:prosper2.net
NetBIOSドメイン名:PROSPER2

LDAPグループ検索用ユーザ

dn: CN=searchuser,CN=Users,DC=prosper2,DC=net
sAMAccountName: searchuser
userPrincipalName: searchuser@prosper2.net
パスワード:s3arch#PWD

SSLを終端するためのCA証明書

秘密鍵ファイル名:icaprivkey.pem
証明書ファイル名:icacert.pem
X509v3基本制限(critical): CA
X509v3鍵使用法(critical): Digital Signature, Certificate Sign, CRL Sign

Docker環境

Dockerコンテナ
コンテナ名:proxy-ad
ホスト名:proxy-ad
ポートバインド:8081:8081/tcp

Dockerネットワーク
IPv6:有効
サブネット:fd5a:ceb9:ed8d:a::/64
ネットワーク名:br_proxy_nw

作業内容

事前準備

ADユーザの準備

以下のユーザを作成しておく。
squid検索ユーザ以外は、既存のユーザにセキュリティグループを割り当ててもOK

ユーザ種別 ユーザ名 OU セキュリティグループ
通常ユーザ josys.saburo employee -
一部許可ユーザ jinji.jiro employee ProxyLimit
全許可ユーザ soumu.taro employee ProxyUnlimit
squid検索ユーザ searchuser - -

なお、検索用ユーザはLDAPでアクセスするだけなので、対話ログインができないようにポリシーで制御しておいたほうがよいでしょう。

Screenshot from Gyazo

searchuserのパスワードは s3arch#PWD として説明します。

証明書の準備

参考エントリ
ActiveDirectory証明機関(ADCS)から中間CAを生成する
OpenSSLでプライベート認証局の構築(ルートCA、中間CA)

SSLインターセプトのため、中間CAでSSLを終端しています。
参考エントリは自身の環境の例で説明していますが、中間CAの機能を有していればどのような方法で取得しても問題ありません。
ブラウザでアクセスするクライアント側には、生成した中間CAの上位となるCAの証明書をインストールしておきます。

dockerネットワークのIPv6化

参考エントリ
dockerネットワークのipv6対応方法と通信経路の整理

squidがIPv6で自分自身にアクセスするため、dockerもIPv6にする必要があります。

dockerコンテナ

docker-compose.yml でまとめてしまいたかったのですが、compose v3は、IPv6指定ができないので、ネットワーク作成は手動です。

構成ファイルの準備

ファイル構成

# tree ./ --charset=C
./
|-- docker-compose.yml
`-- proxy-ad
    |-- Dockerfile
    |-- blacklist
    |-- docker-entrypoint.sh
    |-- icacert.pem
    |-- icaprivkey.pem
    |-- intralist
    |-- permlist
    |-- rsyslog.conf
    |-- smb.conf
    |-- squid.conf
    |-- squid_log
    `-- whitelist

Dockerfile

docker-compose.yml
version: '3'

services:

  proxy-ad:
    build: ./proxy-ad
    image: infraserv:proxy-ad
    container_name: proxy-ad
    hostname: proxy-ad
    restart: always
    networks:
      br_proxy_nw:
    ports:
      - 8081:8081
    cap_add:
      - SYS_ADMIN
    security_opt:
      - seccomp:unconfined
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:ro
    environment:
      TZ: 'Asia/Tokyo'

networks:
  br_proxy_nw:
    external: true
proxy-ad/Dockerfile
FROM centos:centos8
RUN  ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime ; \
     dnf -y update ; dnf -y install epel-release rsyslog logrotate cronie ; \
     rm -f /etc/logrotate.d/syslog ; \
     dnf -y install squid samba samba-winbind openldap-clients authselect samba-winbind-clients ; \
     mkdir /etc/squid/certs ;\
     systemctl enable squid
COPY squid.conf /etc/squid
COPY icacert.pem /etc/squid/certs
COPY icaprivkey.pem /etc/squid/certs
COPY squid_log /etc/logrotate.d
COPY blacklist /etc/squid
COPY whitelist /etc/squid
COPY permlist  /etc/squid
COPY intralist /etc/squid
COPY rsyslog.conf /etc
COPY smb.conf /etc/samba
COPY docker-entrypoint.sh /usr/local/bin/
RUN  mkdir /var/local/squid ;\
     /usr/lib64/squid/security_file_certgen -c -s /var/local/squid/ssl_db -M 4MB ;\
     chown -R squid.squid /var/local/squid ;\
     ln -s usr/local/bin/docker-entrypoint.sh /
ENTRYPOINT ["docker-entrypoint.sh"]
CMD [ "/usr/sbin/init" ]

docker-entrypoint.sh はヘルパースクリプトとして実行権限を与える必要があります。
以下ファイルを作成したら、 chmod 755 docker-entrypoint.sh で権限付与してください。

proxy-ad/docker-entrypoint.sh
#!/bin/sh

if [ ! -e /etc/systemd/system/multi-user.target.wants/smb.service ] ; then
  authselect select winbind --force
  net ads join -U searchuser%s3arch#PWD
  systemctl enable smb
  systemctl enable winbind
  systemctl start smb
  systemctl start winbind
fi

exec "$@"

samba

ドメイン名などは適宜修正してください。

proxy-ad/smb.conf
[global]
        workgroup = PROSPER2
        server string = proxy-ad
        security = ads
        hosts allow = 127.
        realm = PROSPER2.NET

squid

proxy-ad/squid.conf
# ------------------------------------------------------
#  authentication helpers
# ------------------------------------------------------

# NTLM authentication helper : ActiveDirectory SSO
#  max processes : 5
auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
auth_param ntlm children 5

# LDAP search helper : check ActiveDirectory Security Group
#  -v 3  : use LDAP version 3
#  -P    : persistent LDAP connection
#  -R    : do not follow referrals
#  -S    : Strip Domain name
#  -b    : Base DN (search group)
#  -D -w : bind DN (search user) and password
#  -h    : LDAP server (AD DS)
#  -f    : filter %u:User %g:Gourp
#  %LOGIN : SSO login user
external_acl_type security_group %LOGIN /usr/lib64/squid/ext_ldap_group_acl -v 3 -P -R -S -b "ou=employee,dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241 -f '(&(objectclass=person)(sAMAccountName=%u)(memberOf=CN=%g,ou=employee,dc=prosper2,dc=net))'

external_acl_type ou_check %LOGIN /usr/lib64/squid/ext_ldap_group_acl -v 3 -P -R -S -b "ou=employee,dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241 -f '(&(objectclass=person)(sAMAccountName=%u))'

acl gr_unlimit   external security_group ProxyUnlimit
acl gr_limit     external security_group ProxyLimit
acl gr_employee  external ou_check       employee


# ------------------------------------------------------
#  original rules
# ------------------------------------------------------
acl manager proto cache_object
acl localhost src localhost
acl localhost src 127.0.0.1/32

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
#acl Safe_ports port 70          # gopher
#acl Safe_ports port 210         # wais
#acl Safe_ports port 1025-65535  # unregistered ports
#acl Safe_ports port 280         # http-mgmt
#acl Safe_ports port 488         # gss-http
#acl Safe_ports port 591         # filemaker
#acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

# Allow cache
http_access allow localhost manager
http_access deny manager

# Deny not Safe_ports
http_access deny !Safe_ports

# Deny CONNECT request on not SSL_ports
http_access deny CONNECT !SSL_ports


# ------------------------------------------------------
#  user rules
# ------------------------------------------------------

# Deny Blacklist sites
acl blacklist  url_regex -i "/etc/squid/blacklist"
http_access deny blacklist

# Allow Whitelist sites
acl whitelist  url_regex -i "/etc/squid/whitelist"
http_access allow whitelist

# Deny not Domain User
http_access deny !gr_unlimit !gr_limit !gr_employee

# permit : ProxyUnlimit
http_access allow gr_unlimit

# permit : ProxyLimit and permlist
acl permlist   url_regex -i "/etc/squid/permlist"
http_access allow gr_limit permlist

# permit : No security gourp and intralist
acl intralist  url_regex -i "/etc/squid/intralist"
http_access allow gr_employee intralist

# deny : default
http_access deny all


# ------------------------------------------------------
#  SSL BUMP exeption whitelist
# ------------------------------------------------------

http_port 8081 ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/etc/squid/certs/icacert.pem key=/etc/squid/certs/icaprivkey.pem
sslcrtd_program /usr/lib64/squid/security_file_certgen -s /var/local/squid/ssl_db -M 4MB
sslcrtd_children 5
ssl_bump bump !whitelist
sslproxy_cert_error allow intralist
sslproxy_cert_error deny all


# ------------------------------------------------------
#  default options
# ------------------------------------------------------
visible_hostname proxy-ad

coredump_dir /var/spool/squid
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

URLフィルタのリスト

ブラックリストは空のファイルでも大丈夫です。
後述する動作確認の際のリストと同一です。

proxy-ad/blacklist
qiita.com/bashaway

ホワイトリストはひとまずwindowsとcentos(yum)の対応としています。
後述する動作確認の際のリストと同一です。

proxy-ad/whitelist
microsoft.com
www.msftconnecttest.com
onecs-live.azureedge.net
windowsupdate.com
google.com
google-analytics.com
fedoraproject.org
centos.org
ftp.nara.wide.ad.jp
ftp.jaist.ac.jp
ftp.riken.jp
ftp.iij.ad.jp
ftp.tsukuba.wide.ad.jp
mirror.fairway.ne.jp
ftp.yz.yamagata-u.ac.jp
ftp-srv2.kddilabs.jp
yum.mariadb.org

一部許可リストはブラックリストとの比較のため、これにしています。
後述する動作確認の際のリストと同一です。

proxy-ad/permlist
qiita.com

イントラ用リストも通信確認のため、以下をサンプルにしていますが、ADのドメインとあわせておくとよいでしょう。

proxy-ad/intralist
ugtop.com

syslog

syslogという名前で引けるサーバにむけて514/udpでsyslogを投げます。
対象は access.log cache.log の2種類です。

proxy-ad/rsyslog.conf
module(load="imfile")
input(type="imfile"
      file="/var/log/squid/access.log"
      tag="pseudolog_squid_access_log"
      facility="local0"
      severity="notice")
:syslogtag, isequal, "pseudolog_squid_access_log" @syslog:514
input(type="imfile"
      file="/var/log/squid/cache.log"
      tag="pseudolog_squid_cache_log"
      facility="local0"
      severity="notice")
:syslogtag, isequal, "pseudolog_squid_cache_log" @syslog:514

ログがたまるので、1週間でローテートします。

proxy-ad/squid_log
/var/log/squid/*.log {
        daily
        rotate 8
        compress
        missingok
        notifempty
        postrotate
          /bin/systemctl restart rsyslog
        endscript
}

証明書

このほか、証明書の準備 で作成した、秘密鍵と証明書も同じディレクトリに配置します。

コンテナの作成

まず、IPv6のネットワークをつくります。
サブネットは適宜修正ください。

# docker network create --ipv6  --driver=bridge  --subnet=fd5a:ceb9:ed8d:a::/64 br_proxy_nw

でネットワークをつくったら、IPv6が有効になっているかを確認します。

# docker network inspect br_proxy_nw | grep IPv6
        "EnableIPv6": true,

ビルドし、コンテナを起動させます。

# docker-compose build
# docker-compose up -d

動作確認

テストには上記の構成ファイルの説明で例示した URLフィルタのリスト を利用します。

動作確認用のユーザは前述の ADユーザの準備 で作成した、以下を利用します。

カテゴリ ユーザ名
全許可ユーザ soumu.tarp
一部許可ユーザ jinji.jiro
通常ユーザ josys.saburo
非ドメインユーザ ローカルadministrator
認証ダイアログ表示はキャンセルする

アクセス先と想定される動作は以下です。

URL 想定される動作
https://ftp.riken.jp/ 全員アクセスOK
https://ugtop.com/ OU=employee所属の
ユーザはアクセスOK
https://qiita.com/ OU=employee所属で
セキュリティグループがProxyUnlimit/ProxyLimitの
ユーザはアクセスOK
https://crt.sh/ OU=employee所属で
セキュリティグループがProxyUnlimitの
ユーザはアクセスOK
https://qiita.com/bashaway 全員アクセスNG

また、非ドメインユーザの確認として、CentOSのyumアップデートを実施します。

全許可ユーザ(soumu.taro)

https://ftp.riken.jp/
アクセスOK

TCP_TUNNEL/200 8880 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -

https://ugtop.com/
アクセスOK

TCP_DENIED/407 4061 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT ugtop.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT ugtop.com:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/200 2499 GET https://ugtop.com/ PROSPER2\\soumu.taro HIER_DIRECT/219.94.129.26 text/html
TCP_MISS/304 235 GET https://ugtop.com/index.css PROSPER2\\soumu.taro HIER_DIRECT/219.94.129.26 -
TCP_MISS/304 233 GET https://ugtop.com/title2002.gif PROSPER2\\soumu.taro HIER_DIRECT/219.94.129.26 -
TCP_DENIED/407 4120 GET http://www.ugtop.com/favicon.ico - HIER_NONE/- text/html
TCP_DENIED/407 4482 GET http://www.ugtop.com/favicon.ico - HIER_NONE/- text/html
TCP_MISS/302 556 GET http://www.ugtop.com/favicon.ico PROSPER2\\soumu.taro HIER_DIRECT/219.94.129.26 text/html

https://qiita.com/
アクセスOK

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT qiita.com:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/200 16714 GET https://qiita.com/ PROSPER2\\soumu.taro HIER_DIRECT/2406:da14:add:900:a151:96dc:63d3:7b6 text/html
TCP_DENIED/407 4077 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4439 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT cdn.qiita.com:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/304 435 GET https://cdn.qiita.com/assets/public/style-62725e4620e989e818f0a740fac95a08.min.css PROSPER2\\soumu.taro HIER_DIRECT/2600:9000:208e:bc00:13:f1f4:ebc0:93a1 -
TCP_MISS/304 435 GET https://cdn.qiita.com/assets/public/bundle-64959777c315371f97ccc3068267aeec.min.js PROSPER2\\soumu.taro HIER_DIRECT/2600:9000:208e:bc00:13:f1f4:ebc0:93a1 -
TCP_DENIED/407 4077 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4439 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
TCP_MISS/304 453 GET https://cdn.qiita.com/assets/public/hero-background-885fd333ab5d2e15054b2b2b3b970ebc.png PROSPER2\\soumu.taro HIER_DIRECT/2600:9000:208e:bc00:13:f1f4:ebc0:93a1 -
NONE/200 0 CONNECT cdn.qiita.com:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/304 545 GET https://cdn.qiita.com/assets/public/fontawesome-webfont-674f50d287a8c48dc19ba404d20fe713.eot? PROSPER2\\soumu.taro HIER_DIRECT/2600:9000:208e:bc00:13:f1f4:ebc0:93a1 -

https://crt.sh/
アクセスOK

TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT crt.sh:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/200 4530 GET https://crt.sh/ PROSPER2\\soumu.taro HIER_DIRECT/2a0e:ac00:c7:d449::5bc7:d449 text/html
TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT crt.sh:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/200 4820 GET https://crt.sh/sectigo_s.png PROSPER2\\soumu.taro HIER_DIRECT/2a0e:ac00:c7:d449::5bc7:d449 image/png

https://qiita.com/bashaway
アクセスNG

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT qiita.com:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_DENIED/403 4604 GET https://qiita.com/bashaway PROSPER2\\soumu.taro HIER_NONE/- text/html
TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT qiita.com:443 PROSPER2\\soumu.taro HIER_NONE/- -

一部許可ユーザ(jinji.jiro)

https://ftp.riken.jp/
アクセスOK

TCP_TUNNEL/200 8880 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -

https://ugtop.com/
アクセスOK

TCP_DENIED/407 4061 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT ugtop.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT ugtop.com:443 PROSPER2\\jinji.jiro HIER_NONE/- -
TCP_MISS/200 2499 GET https://ugtop.com/ PROSPER2\\jinji.jiro HIER_DIRECT/219.94.129.26 text/html
TCP_MISS/304 235 GET https://ugtop.com/index.css PROSPER2\\jinji.jiro HIER_DIRECT/219.94.129.26 -
TCP_MISS/304 233 GET https://ugtop.com/title2002.gif PROSPER2\\jinji.jiro HIER_DIRECT/219.94.129.26 -
TCP_DENIED/407 4120 GET http://www.ugtop.com/favicon.ico - HIER_NONE/- text/html
TCP_DENIED/407 4482 GET http://www.ugtop.com/favicon.ico - HIER_NONE/- text/html
TCP_MISS/302 556 GET http://www.ugtop.com/favicon.ico PROSPER2\\jinji.jiro HIER_DIRECT/219.94.129.26 text/html

https://qiita.com/
アクセスOK

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT qiita.com:443 PROSPER2\\jinji.jiro HIER_NONE/- -
TCP_MISS/200 16734 GET https://qiita.com/ PROSPER2\\jinji.jiro HIER_DIRECT/2406:da14:add:902:a992:3bc3:1c46:cdfa text/html
TCP_DENIED/407 4077 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4439 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT cdn.qiita.com:443 PROSPER2\\jinji.jiro HIER_NONE/- -
TCP_MISS/304 435 GET https://cdn.qiita.com/assets/public/style-62725e4620e989e818f0a740fac95a08.min.css PROSPER2\\jinji.jiro HIER_DIRECT/2600:9000:208e:ca00:13:f1f4:ebc0:93a1 -
TCP_MISS/304 435 GET https://cdn.qiita.com/assets/public/bundle-64959777c315371f97ccc3068267aeec.min.js PROSPER2\\jinji.jiro HIER_DIRECT/2600:9000:208e:ca00:13:f1f4:ebc0:93a1 -
TCP_DENIED/407 4077 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
TCP_MISS/304 453 GET https://cdn.qiita.com/assets/public/hero-background-885fd333ab5d2e15054b2b2b3b970ebc.png PROSPER2\\jinji.jiro HIER_DIRECT/2600:9000:208e:ca00:13:f1f4:ebc0:93a1 -
TCP_DENIED/407 4439 CONNECT cdn.qiita.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT cdn.qiita.com:443 PROSPER2\\jinji.jiro HIER_NONE/- -
TCP_MISS/304 545 GET https://cdn.qiita.com/assets/public/fontawesome-webfont-674f50d287a8c48dc19ba404d20fe713.eot? PROSPER2\\jinji.jiro HIER_DIRECT/2600:9000:208e:ca00:13:f1f4:ebc0:93a1 -

https://crt.sh/

TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT crt.sh:443 PROSPER2\\jinji.jiro HIER_NONE/- -
NONE/403 4622 GET https://crt.sh/ PROSPER2\\jinji.jiro HIER_NONE/- text/html
TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT crt.sh:443 PROSPER2\\jinji.jiro HIER_NONE/- -

https://qiita.com/bashaway

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT qiita.com:443 PROSPER2\\jinji.jiro HIER_NONE/- -
NONE/403 4633 GET https://qiita.com/bashaway PROSPER2\\jinji.jiro HIER_NONE/- text/html
TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT qiita.com:443 PROSPER2\\jinji.jiro HIER_NONE/- -

通常ユーザの場合(josys.saburo)

https://ftp.riken.jp/
アクセスOK

TCP_TUNNEL/200 8880 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -

https://ugtop.com/
アクセスOK

TCP_DENIED/407 4061 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT ugtop.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT ugtop.com:443 PROSPER2\\josys.saburo HIER_NONE/- -
TCP_MISS/200 2499 GET https://ugtop.com/ PROSPER2\\josys.saburo HIER_DIRECT/219.94.129.26 text/html
TCP_MISS/304 235 GET https://ugtop.com/index.css PROSPER2\\josys.saburo HIER_DIRECT/219.94.129.26 -
TCP_MISS/304 233 GET https://ugtop.com/title2002.gif PROSPER2\\josys.saburo HIER_DIRECT/219.94.129.26 -
TCP_DENIED/407 4120 GET http://www.ugtop.com/favicon.ico - HIER_NONE/- text/html
TCP_DENIED/407 4482 GET http://www.ugtop.com/favicon.ico - HIER_NONE/- text/html
TCP_MISS/302 556 GET http://www.ugtop.com/favicon.ico PROSPER2\\josys.saburo HIER_DIRECT/219.94.129.26 text/html

https://qiita.com/
アクセスNG

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT qiita.com:443 PROSPER2\\josys.saburo HIER_NONE/- -
NONE/403 4667 GET https://qiita.com/ PROSPER2\\josys.saburo HIER_NONE/- text/html
TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT qiita.com:443 PROSPER2\\josys.saburo HIER_NONE/- -

https://crt.sh/
アクセスNG

TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT crt.sh:443 PROSPER2\\josys.saburo HIER_NONE/- -
NONE/403 4660 GET https://crt.sh/ PROSPER2\\josys.saburo HIER_NONE/- text/html
TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT crt.sh:443 PROSPER2\\josys.saburo HIER_NONE/- -

https://qiita.com/bashaway
アクセスNG

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT qiita.com:443 PROSPER2\\josys.saburo HIER_NONE/- -
NONE/403 4669 GET https://qiita.com/bashaway PROSPER2\\josys.saburo HIER_NONE/- text/html
TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT qiita.com:443 PROSPER2\\josys.saburo HIER_NONE/- -

非ドメインユーザで認証キャンセル

ローカルユーザでログインすると、ダイアログが表示されるので、「キャンセル」で閉じる
Screenshot from Gyazo

https://ftp.riken.jp/
アクセスOK

TCP_TUNNEL/200 8880 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -

https://ugtop.com/
アクセスNG

TCP_DENIED/407 4061 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4750 CONNECT ugtop.com:443 PROSPER2\\administrator HIER_NONE/- text/html

https://qiita.com/
アクセスNG

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4754 CONNECT qiita.com:443 PROSPER2\\administrator HIER_NONE/- text/html

https://crt.sh/
アクセスNG

TCP_DENIED/407 4049 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/407 4740 CONNECT crt.sh:443 PROSPER2\\administrator HIER_NONE/- text/html

https://qiita.com/bashaway
アクセスNG

TCP_DENIED/407 4061 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT qiita.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4750 CONNECT qiita.com:443 PROSPER2\\administrator HIER_NONE/- text/html

この時の接続エラーはsquidのエラーページではなく、ブラウザのエラーページとなります。
Screenshot from Gyazo

システムユーザ(yumコマンドによるリポジトリへのアクセス)

以下のようにproxy設定を追記する。

/etc/yum.conf
--------8<----(snip)----8<--------
proxy=http://proxy-ad.prosper2.net:8081/
--------8<----(snip)----8<--------

あとは、 yum update を走らせる。

TCP_MISS/200 995 GET http://mirrorlist.centos.org/? - HIER_DIRECT/2604:1580:fe02:2::10 text/plain
TCP_MISS/200 1025 GET http://mirrorlist.centos.org/? - HIER_DIRECT/2604:1580:fe02:2::10 text/plain
TCP_MISS/200 1049 GET http://mirrorlist.centos.org/? - HIER_DIRECT/2604:1580:fe02:2::10 text/plain
TCP_MISS/200 4110 GET http://ftp.jaist.ac.jp/pub/Linux/CentOS/7.7.1908/os/x86_64/repodata/repomd.xml - HIER_DIRECT/2001:df0:2ed:feed::feed application/xml
TCP_MISS/200 5854 GET http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel/7/x86_64/repodata/repomd.xml - HIER_DIRECT/2001:df0:2ed:feed::feed application/xml
TCP_MISS/200 3367 GET http://ftp.jaist.ac.jp/pub/Linux/CentOS/7.7.1908/extras/x86_64/repodata/repomd.xml - HIER_DIRECT/2001:df0:2ed:feed::feed application/xml
TCP_MISS/200 3334 GET http://yum.mariadb.org/10.4/centos7-amd64/repodata/repomd.xml - HIER_DIRECT/142.4.217.28 application/xml
TCP_MISS/200 3381 GET http://ftp.jaist.ac.jp/pub/Linux/CentOS/7.7.1908/updates/x86_64/repodata/repomd.xml - HIER_DIRECT/2001:df0:2ed:feed::feed application/xml
TCP_MISS/200 1039445 GET http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel/7/x86_64/repodata/66b3561eb58c5f02cd36cf21cb7a1a0a3f564932bfa268c1113e4f7741f93672-updateinfo.xml.bz2 - HIER_DIRECT/2001:df0:2ed:feed::feed application/x-bzip2
TCP_MISS/200 7053786 GET http://ftp.jaist.ac.jp/pub/Linux/Fedora/epel/7/x86_64/repodata/b4f2590ec8c2474cba36dd314b195fd8df46b7e51fc49eafabdf23b6c0219a23-primary.sqlite.bz2 - HIER_DIRECT/2001:df0:2ed:feed::feed application/x-bzip2
TCP_TUNNEL/200 11011 CONNECT mirrors.fedoraproject.org:443 - HIER_DIRECT/2604:1580:fe00:0:dead:beef:cafe:fed1 -

squidログの中身

whitelistの場合
インターセプトせず、トンネルしていることがわかる。

TCP_TUNNEL/200 8880 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -
TCP_TUNNEL/200 3729 CONNECT ftp.riken.jp:443 - HIER_DIRECT/134.160.38.1 -

ユーザを認識したうえでアクセス可となる場合
コード 407 で認証要求が発せられ、ACLチェック後にAllowされる。

TCP_DENIED/407 4423 CONNECT ugtop.com:443 - HIER_NONE/- text/html
NONE/200 0 CONNECT ugtop.com:443 PROSPER2\\soumu.taro HIER_NONE/- -
TCP_MISS/200 2499 GET https://ugtop.com/ PROSPER2\\soumu.taro HIER_DIRECT/219.94.129.26 text/html

ユーザを認識したうえでアクセス不可となる場合
コード 407 で認証要求が発せられ、ACLチェック後にDenyされる。

TCP_DENIED/407 4411 CONNECT crt.sh:443 - HIER_NONE/- text/html
TCP_DENIED/200 0 CONNECT crt.sh:443 PROSPER2\\jinji.jiro HIER_NONE/- -
NONE/403 4622 GET https://crt.sh/ PROSPER2\\jinji.jiro HIER_NONE/- text/html

認証要求にこたえられない場合
コード 407 で認証要求が発せられ、応じられないので、クライアントとしてエラーになる。(ブラウザのエラー画面)

TCP_DENIED/407 4061 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4423 CONNECT ugtop.com:443 - HIER_NONE/- text/html
TCP_DENIED/407 4750 CONNECT ugtop.com:443 PROSPER2\\administrator HIER_NONE/- text/html

中身の解説

Dockerfile

Dockerfileの順番で解説していきます。

イメージCentOS8を利用してます。
NTLM認証によるAD連携をSSOで行うため、sambaとwinbindを入れています。
最後にSSLインターセプトのための証明書を保管するディレクトリを作成しています。

Dockerfile
FROM centos:centos8
RUN  ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime ; \
     dnf -y update ; dnf -y install epel-release rsyslog logrotate cronie ; \
     rm -f /etc/logrotate.d/syslog ; \
     dnf -y install squid samba samba-winbind openldap-clients authselect samba-winbind-clients ; \
     mkdir /etc/squid/certs ;\
     systemctl enable squid

なお、手動で実施すると、以下のような出力になります。
(最初はディレクトリが無かったのでエラーになっています)

# /usr/lib64/squid/security_file_certgen -c -s /var/local/squid/ssl_db -M 4MB
Initialization SSL db...
/usr/lib64/squid/security_file_certgen: Cannot create /var/local/squid/ssl_db
# mkdir /var/local/squid
# chown squid.squid /var/local/squid
# /usr/lib64/squid/security_file_certgen -c -s /var/local/squid/ssl_db -M 4MB
Initialization SSL db...
Done

ここは必要なファイルをローカルからコンテナへコピーしているだけです。
ファイルは空でもよいですが、ファイル自体が存在していないとエラーになります。

Dockerfile
COPY squid.conf /etc/squid
COPY icacert.pem /etc/squid/certs
COPY icaprivkey.pem /etc/squid/certs
COPY squid_log /etc/logrotate.d
COPY blacklist /etc/squid
COPY whitelist /etc/squid
COPY permlist  /etc/squid
COPY intralist /etc/squid
COPY rsyslog.conf /etc
COPY smb.conf /etc/samba
COPY docker-entrypoint.sh /usr/local/bin/

squidでSSLインターセプトするため、一時的にsquid自身がアクセス先のサーバ証明書を作成します。
そのサーバ証明書を入れておくディレクトリの作成と、ディレクトリの初期化を行います。
squidがアクセスする必要があるので、オーナーを変更します。

Dockerfile
RUN  mkdir /var/local/squid ;\
     /usr/lib64/squid/security_file_certgen -c -s /var/local/squid/ssl_db -M 4MB ;\
     chown -R squid.squid /var/local/squid ;\

初回起動時の処理を行うためのヘルパースクリプトをコンテナ内にコピーしています。

Dockerfile
     ln -s usr/local/bin/docker-entrypoint.sh /
ENTRYPOINT ["docker-entrypoint.sh"]
CMD [ "/usr/sbin/init" ]

docker-entrypoint.sh

初回起動時のみ処理させたいものをここにまとめています。
ヘルパースクリプトの動作は dockerで初回起動時のみ特定の処理を行うヘルパースクリプト に書きました。

smbとwinbindはインストールしただけでは、enableになっていないので、それを初回起動の判断条件としています。
認証にwinbindを利用するコマンドを実施後、 net ads join -U で自身のコンピュータをADに登録します。
登録時はドメインユーザであればOKですので、検索用に作成したユーザを指定しています。
その後、sambaとwinbindを有効化しています。

docker-entrypoint.sh
#!/bin/sh

if [ ! -e /etc/systemd/system/multi-user.target.wants/smb.service ] ; then
  authselect select winbind --force
  net ads join -U searchuser%s3arch#PWD
  systemctl enable smb
  systemctl enable winbind
  systemctl start smb
  systemctl start winbind
fi

exec "$@"

なお、手動で実施すると、以下のような出力になります。

# net ads join -U searchuser%s3arch#PWD
Using short domain name -- PROSPER2
Joined 'PROXY-AD' to dns domain 'prosper2.net'
No DNS domain configured for proxy-ad. Unable to perform DNS Update.
DNS update failed: NT_STATUS_INVALID_PARAMETER

エラーっぽい出力になっていますが、以下のようにコンピュータが登録されます。
Screenshot from Gyazo

squid.conf

認証がらみが多く出てきます。
各セクションごとに説明しますが、コメントは外しています。

NTLM認証のヘルパーを使います。
以下設定では子プロセスを5としているので、大量のユーザで利用する場合は、チューニングが必要です。

squid.conf
auth_param ntlm program /usr/bin/ntlm_auth --helper-protocol=squid-2.5-ntlmssp
auth_param ntlm children 5

ここは、SSOのユーザがどのセキュリティグループに所属しているのかを ext_ldap_group_acl でチェックします。
セキュリティグループがProxyUnlimitなら、squid内でgr_unlimitというaclを定義しています。
セキュリティグループがProxyLimitなら、squid内でgr_limitというaclを定義しています。
このままだと、どちらのセキュリティグループにも所属していないと、後にでてくる http_access で不具合がでます。
なので、 ext_ldap_group_acl を再度処理して、SSOユーザがOU=employeeに所属していれば、 gr_employee をいうaclを定義しています。
ベースDNをそのままにして、検索フィルタでOUを抜き出したいのですが、OU=employee配下のユーザでOU=employee配下のセキュリティグループに所属していないと、memberOf属性で検索ができない。加えて、DN属性にはワイルドカードが利用できないので、 CN=*,OU=employee,DC=prosper2,DC=net という検索ができない。そのため、このような回避策をしています。

squid.conf
external_acl_type security_group %LOGIN /usr/lib64/squid/ext_ldap_group_acl -v 3 -P -R -S -b "ou=employee,dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241 -f '(&(objectclass=person)(sAMAccountName=%u)(memberOf=CN=%g,ou=employee,dc=prosper2,dc=net))'

external_acl_type ou_check %LOGIN /usr/lib64/squid/ext_ldap_group_acl -v 3 -P -R -S -b "ou=employee,dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241 -f '(&(objectclass=person)(sAMAccountName=%u))'

acl gr_unlimit   external security_group ProxyUnlimit
acl gr_limit     external security_group ProxyLimit
acl gr_employee  external ou_check       employee

ext_ldap_group_acl のオプションなどは、以下のとおりです。

# LDAP search helper : check ActiveDirectory Security Group
#  -v 3  : use LDAP version 3
#  -P    : persistent LDAP connection
#  -R    : do not follow referrals
#  -S    : Strip Domain name
#  -b    : Base DN (search group)
#  -D -w : bind DN (search user) and password
#  -h    : LDAP server (AD DS)
#  -f    : filter %u:User %g:Gourp
#  %LOGIN : SSO login user

このあたりは、デフォルトの動作とほぼ同じです。
ただし、proxyで許可するポートを http/https/ftp に限定しています。

squid.conf
acl manager proto cache_object
acl localhost src localhost
acl localhost src 127.0.0.1/32

acl SSL_ports port 443
acl Safe_ports port 80          # http
acl Safe_ports port 21          # ftp
acl Safe_ports port 443         # https
#acl Safe_ports port 70          # gopher
#acl Safe_ports port 210         # wais
#acl Safe_ports port 1025-65535  # unregistered ports
#acl Safe_ports port 280         # http-mgmt
#acl Safe_ports port 488         # gss-http
#acl Safe_ports port 591         # filemaker
#acl Safe_ports port 777         # multiling http
acl CONNECT method CONNECT

# Allow cache
http_access allow localhost manager
http_access deny manager

# Deny not Safe_ports
http_access deny !Safe_ports

# Deny CONNECT request on not SSL_ports
http_access deny CONNECT !SSL_ports

squidの条件判定はFWなんかと同じで、上からチェックしてマッチしたらそこで終了です。
前述した ext_ldap_group_acl は http_access句でチェックされようとするタイミングで発動するため、blacklistとwhitelistはldap処理の前にもってきています。

squid.conf
# Deny Blacklist sites
acl blacklist  url_regex -i "/etc/squid/blacklist"
http_access deny blacklist

# Allow Whitelist sites
acl whitelist  url_regex -i "/etc/squid/whitelist"
http_access allow whitelist

ドメインユーザでなければ拒否します。(ホワイトリストは前述でallowのため、影響ありません。)

squid.conf
# Deny not Domain User
http_access deny !gr_unlimit !gr_limit !gr_employee

セキュリティグループ:ProxyUnlimit は、接続先によらず許可です。

squid.conf
# permit : ProxyUnlimit
http_access allow gr_unlimit

セキュリティグループ:ProxyLimit は、permlistにあるサイトは許可です。

squid.conf
# permit : ProxyLimit and permlist
acl permlist   url_regex -i "/etc/squid/permlist"
http_access allow gr_limit permlist

OU:employeeのユーザはintralistにあるサイトは許可です。

squid.conf
# permit : No security gourp and intralist
acl intralist  url_regex -i "/etc/squid/intralist"
http_access allow gr_employee intralist

これまでに許可されなかったクライアントは拒否です。

squid.conf
# deny : default
http_access deny all

待ち受けを8081/tcpとして、SSL_BUMPしています。
SSL_BUMPは子プロセスを5としているので、大量のユーザで利用する場合は、チューニングが必要です。
whitelistはSSL_BUMPせず、そのまま転送します。(これしないと yum でエラー出る)

squid.conf
http_port 8081 ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/etc/squid/certs/icacert.pem key=/etc/squid/certs/icaprivkey.pem
sslcrtd_program /usr/lib64/squid/security_file_certgen -s /var/local/squid/ssl_db -M 4MB
sslcrtd_children 5
ssl_bump bump !whitelist
sslproxy_cert_error allow intralist
sslproxy_cert_error deny all

あとはデフォルトのまま。

squid.conf
visible_hostname proxy-ad

coredump_dir /var/spool/squid
refresh_pattern ^ftp:           1440    20%     10080
refresh_pattern ^gopher:        1440    0%      1440
refresh_pattern -i (/cgi-bin/|\?) 0     0%      0
refresh_pattern .               0       20%     4320

トラブルシューティング

winbindがうまく動作しない場合、ldapフィルタが思うように動作しない場合など、以下の通りチェックしてみます。

winbindの動作

正常に接続できるかの確認

# wbinfo -t
checking the trust secret for domain PROSPER2 via RPC calls succeeded

ユーザリストが取得できるか

# wbinfo -u
PROSPER2\administrator
PROSPER2\guest
PROSPER2\krbtgt
PROSPER2\aad_7dfc1e6f942a
PROSPER2\msol_7dfc1e6f942a
PROSPER2\soumu.taro
PROSPER2\jinji.jiro
PROSPER2\josys.saburo
PROSPER2\searchuser

指定ユーザで認証できるか

# wbinfo -a PROSPER2.NET\\searchuser%s3arch#PWD
plaintext password authentication succeeded
challenge/response password authentication succeeded

ldapsearch

windowsのログインユーザを指定して、対象ユーザの情報を表示

# ldapsearch -b "dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241   "sAMAccountName=soumu.taro" 

フィルタを組み合わせて、対象ユーザの情報を表示

# ldapsearch -b "dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241  \
  '(&(objectclass=person)(sAMAccountName=soumu.taro)(memberOf=CN=ProxyUnlimit,OU=employee,DC=prosper2,DC=net))'

フィルタを組み合わせて、対象ユーザの情報を表示
(この場合、jinji.jiroはProxyUnlimitのmemberOfではないため、表示されない)

# ldapsearch -b "dc=prosper2,dc=net" -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241  \
  '(&(objectclass=person)(sAMAccountName=jinji.jiro)(memberOf=CN=ProxyUnlimit,OU=employee,DC=prosper2,DC=net))'

ext_ldap_group_acl

squid.conf で記載しているコマンドは、そのままコマンドラインで確認できる。
ログイン名とセキュリティグループの組み合わせが正しいかをチェック

# /usr/lib64/squid/ext_ldap_group_acl -v 3 -P -R -S -b "dc=prosper2,dc=net" \
  -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241 \
  -f '(&(objectclass=person)(sAMAccountName=%u)(memberOf=CN=%g,ou=employee,dc=prosper2,dc=net))'
soumu.taro   ProxyUnlimit
OK
jinji.jiro   ProxyUnlimit
ERR
josys.saburo ProxyUnlimit
ERR
soumu.taro   ProxyLimit
ERR
jinji.jiro   ProxyLimit
OK
josys.saburo ProxyLimit
ERR

ログイン名とがOU:employeeに存在するかをチェック
(引数を1つしか指定していないため、第2引数はなんの文字列でもかまわない)

# /usr/lib64/squid/ext_ldap_group_acl -v 3 -P -R -S -b "ou=employee,dc=prosper2,dc=net" \
  -D searchuser@prosper2.net -w s3arch#PWD -h 10.254.10.241 \
  -f '(&(objectclass=person)(sAMAccountName=%u))'
soumu.taro   ABCDEFG
OK
jinji.jiro   ABCDEFG
OK
josys.saburo ABCDEFG
OK
searchuser   ABCDEFG
ERR

さいごに

前回チャレンジしたのが2014年の squidとActiveDirectoryの連携 でした。
今回はSSLインターセプトを追加してDockerコンテナで作成しましたが、squid4.4になっても大きく変わっていなかったので、比較的すんなり検証できました。

次はKerberos認証にチャレンジ予定です。

出典

http://www.prosper2.org/devwiki/index.php?squid%E3%81%A8ActiveDirectory%E3%81%AE%E9%80%A3%E6%90%BA
https://www7390uo.sakura.ne.jp/wordpress/archives/777
https://smoothnet.org/squid-v3-5-proxy-with-ssl-bump/
https://social.technet.microsoft.com/Forums/lync/en-US/24e0eec0-7984-4bc3-b2e8-319be2d57112/ldap-filter-limiting-to-specific-ou
https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx

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

dockerでsinatraサーバーを起動しよう。

この記事で得られるもの(目的)

  • Virtual MachineとDockerの起動方式
  • Dockerfileの書き方
  • DockerでImageを作る方法
  • DockerでContainerを起動する方法

この記事で扱わないこと

  • Dockerのインストール

Agenda

  1. Dockerとは
  2. Virtual MachineとDockerの起動方式
  3. SintraサーバーのDocker Imageを作る
  4. Imageに基づいたContainerを起動させる

Dockerとは

DockerはImageに基づいてContainerを起動したりするプログラムです。
Containerは隔離された空間でProcessを動く技術です。
ImageはどういうContainerを作るかについて記録されている設計図みたいなことです。

Virtual MachineとDockerの起動方式

Virtual Machineの起動方式
(出処)Dockerホームページ
image.png
例えば、WindowsでLinuxを実行したいとなった場合、
Virtual Machine(Virtual Boxなど)ではHost OS(Windows)の上にGuest OS(Linux)をインストールしてApp Serverを立ち上げることになります。
つまりHost OSとは別のResourceを全部作り直します。

Dockerの起動方式
(出処)Dockerホームページ
image.png
DockerはHost OSのResourceを共有してもらってContainerを起動させる。
だから、VMの方式よりOverheadがかなり少なくなるし、実際使って見ても結構早いですね。

SintraサーバーのDocker Imageを作る

まず、DockerがContainerを実行するまでの簡略な順を見ましょう。
DockerはDockerfileに基づいてDocker Imageを作ります。
その後、Docker Imageに基づいてDocker Containerを起動させます。

じゃー、SinatraのAppのための環境を作るための書いて見ましょう。

ファイルの位置: /Dockerfile

  1 # baseになるimage
  2 FROM ruby:2.6.5
  3 # このDockerfileを作った人
  4 MAINTAINER jinument@gmail.com
  5
  6 # Docker Containerの環境変数を設定
  7 # ENV 環境変数名 環境変数値
  8 ENV WORKSPACE /app
  9
 10 # HostのファイルをContainer内に追加
 11 # ADD Hostのファイル経路 Container内の経路
 12 # Hostの現在DirectoryにあるGemfileと始まるファイルを
 13 # Container内のWorkspace(ここでは/app)に追加
 14 ADD ./Gemfile* $WORKSPACE/
 15 # Container内の作業Directoryを変更する
 16 # Container内でcd(change directory)コマンドをうつのと同じ
 17 WORKDIR $WORKSPACE
 18 # Container内で実行するコマンドを定義
 19 # このコマンドの意味は
 20 # Container内の/app/でbundle installを実行してという意味
 21 RUN bundle install
 22
 23 ADD . $WORKSPACE
 24
 25 # ContainerのPortを開放する
 26 # このコマンドでHostから4567ポートで
 27 # Container内の4567にアクセスできるようになる
 28 # (参考)Sinatraのサーバーポートが4567だからここで4567を開放する
 29 EXPOSE 4567
 30
 31 # Containerのbuildが出来上がって
 32 # Containerが実行するタイミングでこのコマンドが実行される
 33 CMD ['ruby', 'app.rb']

ファイルの位置: /app.rb

1 require 'sinatra'
2
3 set :bind, '0.0.0.0'
4
5 get '/health_check' do
6   'health check'
7 end

ファイルの位置: /Gemfile

1 source 'https://rubygems.org'
2
3 gem 'sinatra', '2.0.8'

以下のファイルを同じDirectoryに置いておいて以下のコマンドを実行することで、Docker Imageを作る。
docker build -t sinatra_image .

-t sinatra_imageは作るimageの名前を指定すること。
. は現在DirectoryにあるDockerfileを利用してDocker Imageを作るという意味。

docker build -t sinatra_image .このコマンドを打ったら、Dockerは以下のログを吐き出します。
ログを見ると内がDockerfileに書いた部分が一個づつ実行されることが確認できる。
(Layerという概念もあるが、この記事では扱いません。)

lee@leeui-MacBookAir  ~/workspace/qiita  docker build -t make_image .
Sending build context to Docker daemon  6.144kB
Step 1/9 : FROM ruby:2.6.5
 ---> a161c3e3dda8
Step 2/9 : MAINTAINER jinument@gmail.com
 ---> Running in ce277718c930
Removing intermediate container ce277718c930
 ---> b56f7155a807
Step 3/9 : ENV WORKSPACE /app
 ---> Running in 3869474ae7c2
Removing intermediate container 3869474ae7c2
 ---> d17245751687
Step 4/9 : ADD ./Gemfile* $WORKSPACE/
 ---> 616bacbaa111
Step 5/9 : WORKDIR $WORKSPACE
 ---> Running in 0a6fd625644c
Removing intermediate container 0a6fd625644c                                                                                                                                buffers
 ---> 2ef75a288ed5
Step 6/9 : RUN bundle install
 ---> Running in df916cdef1f6
Fetching gem metadata from https://rubygems.org/..........
Using bundler 1.17.2
Fetching ruby2_keywords 0.0.2
Installing ruby2_keywords 0.0.2
Fetching mustermann 1.1.1
Installing mustermann 1.1.1
Fetching rack 2.2.2
Installing rack 2.2.2
Fetching rack-protection 2.0.8
Installing rack-protection 2.0.8
Fetching tilt 2.0.10
Installing tilt 2.0.10
Fetching sinatra 2.0.8
Installing sinatra 2.0.8
Bundle complete! 1 Gemfile dependency, 7 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
Removing intermediate container df916cdef1f6
 ---> 2ce2af9012c7
Step 7/9 : ADD . $WORKSPACE
 ---> eec1a89dd292
Step 8/9 : EXPOSE 4567
 ---> Running in 4b7d253f9875
Removing intermediate container 4b7d253f9875
 ---> fca62715a481
Step 9/9 : CMD ['ruby', 'app.rb']
 ---> Running in dd5069206a4a
Removing intermediate container dd5069206a4a
 ---> 41e7c0189e0c
Successfully built 41e7c0189e0c
Successfully tagged sinatra_image:latest

じゃー、Imageがちゃんと作られたか以下のコマンドで確認して見ましょう。

⚙ lee@leeui-MacBookAir  ~/workspace/qiita  docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
sinatra_image       latest              41e7c0189e0c        32 minutes ago      872MB

Imageに基づいたContainerを起動させる

⚙ lee@leeui-MacBookAir  ~/workspace/qiita  docker run -d -p 4567:4567 sinatra_image
023f6c6e7d27a7368a3440163c7faeda406c3e8cc36ee7d254e50c56551200af

現状Container化されているものの状況を確認するコマンドは以下になります。

docker ps -a
 ⚙ lee@leeui-MacBookAir  ~/workspace/qiita  docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                       PORTS               NAMES
023f6c6e7d27        sinatra_image     "/bin/sh -c '['ruby'…"   3 minutes ago       Exited (127) 3 minutes ago                       boring_northcutt

localhost:4567/health_checkにアクセスして意図通り動いているか確認します。

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

Dockerでよく使うコマンド

Dockerでよく使うコマンドについて記載

#dockerのバージョン確認
$docker version

#dockerの実行環境確認
$docker info

#イメージをダウンロード
$docker pull [OPTIONS] NAME[:TAG|@DIGEST]
#例
$docker pull centos:7.1.1503

#イメージの一覧を表示
$docker images [OPTIONS] [REPOSITORY[:TAG]]

#イメージの詳細を表示
$docker inspect [OPTIONS] NAME|ID [NAME|ID...]

#イメージへタグを設定
$docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]

#Dokcer Hubに公開されているイメージの検索
$docker search [OPTIONS] TERM

#イメージの更新内容を確認
$docker history [OPTIONS] IMAGE

#イメージの削除
$docker rmi [OPTIONS] IMAGE [IMAGE...]

#Dokcer Hubにログイン
$docker login [OPTIONS] [SERVER]

#Docker Hubにイメージをアップロード
$docker push [OPTIONS] NAME[:TAG]

#コンテナの起動
$docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
#例
$docker run centos:7.1.1503

#デタッチド・モードでの実行 例
docker run --name centos01 -d -p 8080:8080 -m=200m --memory-swap=1G --cpu-shares=1024 centos:7.1.1503

#コンテナをターミナルで実行する 例
$docker run -i -t centos:7.1.1503 /bin/bash

#バックグラウンドで実行しているコンテナをフォアグラウンドにする
$docker attach [OPTION] CONTAINER [CONTAINER...]

#コンテナの一覧を表示
$docker ps [OPTIONS]

#コンテナの一覧を表示(停止したものも表示)
$docker ps -a

#コンテナの稼働確認
$docker stats [OPTIONS] [CONTAINER...]

#コンテナのログを表示
$docker logs [OPTION] CONTAINER [CONTAINER...]

#コンテナのの停止(一定期間が経過したらSIGKILLを送信)
$docker stop [OPTION] CONTAINER [CONTAINER...]

#コンテナのの停止(すぐ停止)
$docker stop [OPTION] CONTAINER [CONTAINER...]

#コンテナの再起動
$docker restart [OPTIONS] CONTAINER [CONTAINER...]

#コンテナの中断
$docker pause CONTAINER [CONTAINER...]

#コンテナの再開
$docker unpause CONTAINER [CONTAINER...]

#起動中のコンテナに入ってプロセスを実行
$docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

#起動中のコンテナに入ってプロセスを実行 例
$docker exec -i -t xxxxxx /bin/bash

#コンテナのプロセス確認
$docker top CONTAINER [ps OPTIONS]

#コンテナのポート確認
$docker port CONTAINER [PRIVATE_PORT[/PROTO]]

#コンテナの名前変更
$docker rename CONTAINER NEW_NAME

#コンテナ内からファイルをコピー
$docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

#コンテナ内からファイルをコピー 例
$docker cp nginx01:/etc/test.ttx /tmp/test.txt

#コンテナ内へファイルをコピー
$docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH

#コンテナ内へファイルをコピー
$docker cp /tmp/test.txt nginx01:/etc/test.txt

#コンテナの削除
$docker rm [OPTIONS] CONTAINER [CONTAINER...]

#コンテナの強制削除
$docker rm -f [OPTIONS] CONTAINER [CONTAINER...]

#止まっているコンテナを全て削除 例
$docker rm $(docker ps -aq --filter='status=exited')

#コンテナへの変更内容を確認するためのコマンド。
$docker diff [OPTIONS] CONTAINER

#例
$docker diff $(docker ps -lq)

#コンテナからイメージを作成
$docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]

#コンテナからイメージを出力
$docker container export [OPTIONS] CONTAINER

#コンテナからイメージを出力 例
$docker container export nginx01 > nginx01.tar

#イメージをインポート
$docker image import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]

#イメージを保存
$docker save [OPTIONS] IMAGE [IMAGE...]

#イメージの読み込み
$docker load [OPTIONS]

#Dockerfileからイメージの作成
$docker build [OPTIONS] PATH | URL | -

#Dockerfileからイメージの作成 例
$docker build https://github.com/docker/rootfs.git#container:docker

以上

参考

http://docs.docker.jp/engine/reference/commandline/index.html

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