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

【docker】noneなimageを一掃したいときの魔法のコマンド

TL;DR

% docker images | grep none | xargs docker rmi `awk '{ print $3 }'`

conflictが起きて削除できないとき

Error response from daemon: conflict: unable to delete 78ef4af0ce83 (must be forced) - image is referenced in multiple repositories

上みたいなエラーが出たときは、-fで強制的に削除してやりましょう

% docker images | grep none | xargs docker rmi -f `awk '{ print $3 }'`
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コンテナ版マインクラフトサーバを構築してhttps化したDynmapを使う

はじめに

本記事ではマインクラフトのサーバをコンテナで構築します。
仮想マシンを作ってJDKをインストールしてjarファイルを実行して・・・というやり方が多いと思います。
このやり方も問題ないですが、サクッと作れるコンテナ版マインクラフト+αをご紹介します。
この方法で以下のようなサーバを作成することができます。

  • Minecraft Forge対応サーバ
  • Forge版のDynmapの表示
  • Dynmapをリバースプロキシ経由にしてhttps化

構成図
kouseizu.png

※前提条件

  • 筆者の環境はCentOS 7です(古くてすみません)
  • DockerとDocker-composeがインストール済
  • 独自ドメイン等でdynmap.yourdomain.com等で名前解決できる
  • マインクラフトのポートTCP:25565(任意)、Let's Encrypt用にTCP:80,443が使える

使うもの紹介

今回使用するコンテナ、MODを紹介します。Forgeを導入しますので、Dynmap以外にも色々導入して大丈夫です。

docker-letsencrypt-nginx-proxy-companion

Nginxベースのリバースプロキシ機能と、Let's Encrypt証明書発行機能をもったコンテナスタックです。
自動で証明書の発行・更新をしつつ、背後のWebサーバのリバースプロキシとして機能します。
証明書発行の認証にはhttp-01チャレンジを使用するのでIN側TCPポート80,443での通信が必要です。
https://github.com/nginx-proxy/docker-letsencrypt-nginx-proxy-companion

itzg/minecraft-server

itzg(Geoff Bourne)氏がメンテナンスするマインクラフトのコンテナ版です。
バニラサーバであればこのコンテナを起動するだけでマインクラフトサーバが立ち上がります。
https://github.com/itzg/docker-minecraft-server

Minecraft Forge

マインクラフトに様々なMODを適用する際の前提MOD。
大体のMODはこのForgeを要求します。今回のDynmapもForgeを使用します(Forge版以外もあります)。
http://files.minecraftforge.net

Dynmap

ウェブブラウザからGoogle MapライクのUIでマインクラフトのワールドを確認できるMODです。
真上、斜め、別ディメンションが確認できて各種マーカーを立てたり、チャット機能があったりと非常に高機能です。
さらに最初から簡易Webサーバも備えているため、別途Webサーバを用意することなく使用できます。
今回はこの簡易Webサーバにリバースプロキシ経由でアクセスします。
https://www.curseforge.com/minecraft/mc-mods/dynmapforge

docker-letsencrypt-nginx-proxy-companionのインストール

これを使うと、Nginxのリバースプロキシ機能とLet's Encryptによるhttps化が可能になります。
例えば独自ドメインをお持ちならhttps://dynmap.yourdomain.com/ のようなアドレスでDynmapにアクセスが可能になります。
マインクラフト以外でも使える便利なDockerスタックなので、今回はdocker-composeファイルを独立させます。
以下のdocker-compose.ymlでコンテナ達を起動してください。

docker-compose.yml
version: '3'

services:
  nginx-proxy:
    image: jwilder/nginx-proxy
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - conf:/etc/nginx/conf.d
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - dhparam:/etc/nginx/dhparam
      - certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
    labels:
      - "com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy"
    restart: always

  letsencrypt:
    image: jrcs/letsencrypt-nginx-proxy-companion
    container_name: nginx-proxy-le
    depends_on:
      - nginx-proxy
    volumes:
      - vhost:/etc/nginx/vhost.d
      - html:/usr/share/nginx/html
      - dhparam:/etc/nginx/dhparam:ro
      - certs:/etc/nginx/certs
      - /var/run/docker.sock:/var/run/docker.sock:ro
    restart: always

volumes:
  conf:
  vhost:
  html:
  dhparam:
  certs:

networks:
  default:
    external:
      name: nginx-proxy
docker-compose
$sudo docker-compose up -d

マインクラフトのインストール

Docker Hubにあるitzg/minecraft-serverを使用します。
Dynmapを入れるディレクトリはmodsディレクトリとなります。
docker-compose.ymlを置くディレクトリで以下を実行してください。

mkdir
$sudo mkdir mods

マインクラフトのdocker-compose.ymlは以下になります。
Dockerネットワーク名は、docker-letsencrypt-nginx-proxy-companionと合わせてください。

docker-compose.yml
version: "3.7"

services:
  mc:
    image: itzg/minecraft-server
    ports:
    - 25565:25565
    - 8123:8123
    environment:
      EULA: "TRUE"
      VERSION: 1.16.4
      DIFFICULTY: normal
      SERVER_NAME: SERVERNAME
      TYPE: FORGE
      FORGEVERSION: 35.1.32
      ANNOUNCE_PLAYER_ACHIEVEMENTS: "true"
      TZ: Asia/Tokyo
      ENABLE_RCON: "true"
      RCON_PASSWORD: "PASSWORD"
      RCON_PORT: 28016
      ENABLE_QUERY: "true"
      ENABLE_STATUS: "true"
      OPS: Operator_Name
      USE_AIKAR_FLAGS: "true"
      MEMORY: 16G
      USE_LARGE_PAGES: "true"
      VIRTUAL_HOST: dynmap.your.domain
      VIRTUAL_PORT: 8123
      LETSENCRYPT_HOST: dynmap.your.domain
      LETSENCRYPT_EMAIL: email@address

    tty: true
    stdin_open: true
    restart: always

    volumes:
    - mc_forge:/data
    - ./mods:/mods:ro

volumes:
  mc_forge: {}

networks:
  default:
    external:
      name: nginx-proxy

以下に、各項目の説明をします。環境によっては不要な項目もあると思いますので、適宜削除などしてください。
また、ゲームに関する変数の詳細(難易度等)は以下リンクを参照してください。
server.properties(Minecraft WIKI)

マインクラフト関係

環境変数 今回の値 説明
EULA "TRUE" マインクラフトの使用許諾に同意(必須)
VERSION 1.16.4 マインクラフトのバージョン
DIFFICULTY normal ゲーム難易度
SERVER_NAME SERVERNAME サーバ名
TYPE FORGE サーバのタイプ。今回はForge。
FORGEVERSION 35.1.32 Forgeのバージョン
ANNOUNCE_PLAYER_ACHIEVEMENTS "true" プレイヤーの達成を表示するかどうか(任意)
TZ Asia/Tokyo タイムゾーン
ENABLE_RCON "true" RCON(マインクラフトの遠隔操作)を有効にする
RCON_PASSWORD "PASSWORD" RCONのパスワード
RCON_PORT 28016 RCONのポート番号
ENABLE_QUERY "true" サーバーの稼働状態の送信を有効
ENABLE_STATUS "true" サーバーの詳細な?稼働状態の送信を有効
OPS Operator_Name サーバオペレータ(OP権限)ユーザの設定
USE_AIKAR_FLAGS "true" Java変数の最適化
MEMORY 16G Javaで確保するメモリ
USE_LARGE_PAGES "true" Javaラージページの設定(メモリ12GB以上)

Dynmap/リバースプロキシ/Let's Encrypt関係

環境変数 今回の値 説明
VIRTUAL_HOST dynmap.your.domain dynmapを表示するFQDN
VIRTUAL_PORT 8123 dynmapのポート番号
LETSENCRYPT_HOST dynmap.your.domain dynmapを表示するFQDN
LETSENCRYPT_EMAIL email@address Let's Encryptから連絡を受けるメールアドレス

次に、modsディレクトリにdynmapを格納します。以下からダウンロードしてmodsディレクトリに入れてください。
https://www.curseforge.com/minecraft/mc-mods/dynmapforge

あとはdocker-compose upすればマインクラフトが起動してきます。

docker-compose
$sudo docker-compose up -d

起動後しばらくすると(1分程度)、docker-letsencrypt-nginx-proxy-companionによってhttps化されます。
https://dynmap.your.domain/でアクセスできるようになっているはずです。
マインクラフト自体ははデフォルトポートであれば通常どおり"your.domain"で接続できます。

うまく起動してこない場合、Dockerのログを確認してみてください。

docker-compose
$sudo docker-compose logs -f 

証明書例
dynmap_example.png

マインクラフト接続例
server_example.png

おわりに

シンプルなマインクラフトサーバの構築はもともと難しいものではありませんでしたが、
コンテナで実行することでマインクラフトもIaCとして管理できます。ほしいマインクラフト環境がすぐに構築できるのはいいですね。
また、dynmapもコンフィグを設定すればリバースプロキシすることができましたが、コンテナ版マインクラフトでもっと簡単にできます。
それでは良いマインクラフトライフを!

おまけ:私の環境では、さらにPrometheusとGrafanaを使ってプレイヤーの状態を確認したりして遊んでます!
example.png

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

Docker上でVSCodeを動かす

目的

開発環境として使用するため、VSCodeが実行されるDockerコンテナを作成します。
下記の通り実行されます。

  • コンテナを起動するとVSCodeがGUIアプリとして起動する
  • VSCodeを起動するユーザーは、コンテナ作成時に指定する

image.png

前提条件

Docker コンテナ上でGUIアプリケーションを動かす(日本語入力)の記事をもとにコンテナイメージを作成していることを前提とします。

Dockerイメージの作成

Dockerfile
FROM sabocla6/ubuntu_ui_jp

# ***********************************************
# install packages for xrdp, and do setting
# ***********************************************
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
        gnupg firefox supervisor

# ***********************************************
# prepare add user
# ***********************************************
RUN chmod u+s /usr/sbin/useradd \
    && chmod u+s /usr/sbin/groupadd \
    && chmod u+s /usr/sbin/chpasswd

COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
RUN echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/ALL

# ***********************************************
# install vscode
# ***********************************************
ADD https://az764295.vo.msecnd.net/stable/ea3859d4ba2f3e577a159bc91e3074c5d85c0523/code_1.52.1-1608136922_amd64.deb /tmp/code.deb
RUN dpkg -i /tmp/code.deb

# ***********************************************
# copy entrypoint shell
# ***********************************************
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
ENTRYPOINT ["docker-entrypoint.sh"]

docker-entrypoint.sh
#!/bin/bash -e

USER_ID=$(id -u)
GROUP_ID=$(id -g)
USER=${USER:-${DEFAULT_USER}}
GROUP=${GROUP:-${USER}}
PASSWD=${PASSWD:-${DEFAULT_PASSWD}}
NeW_USER=false

unset DEFAULT_USER DEFAULT_PASSWD

# Add group
echo ""
if [[ $GROUP_ID != "0" && ! $(getent group $GROUP) ]]; then
    echo "Create New Group GROUP_ID: $GROUP_ID GROUP: $GROUP"
    groupadd -g $GROUP_ID $GROUP
fi

# Add user
if [[ $USER_ID != "0" && ! $(getent passwd $USER) ]]; then
    echo "Create New User USER_ID: $USER_ID USER: $USER"
    export HOME=/home/$USER
    useradd -d ${HOME} -m -s /bin/bash -u $USER_ID -g $GROUP_ID -G 27 $USER
    NeW_USER=true
fi

# Set login user name
USER=$(whoami)
echo "USER: $USER"

# Set login password
echo "PASSWD: $PASSWD"
echo ${USER}:${PASSWD} | sudo chpasswd

# Revert permissions
sudo chmod u-s /usr/sbin/useradd
sudo chmod u-s /usr/sbin/groupadd
sudo chmod u-s /usr/sbin/chpasswd

unset PASSWD
if [[ "$@" = "" ]]; then
    exec /bin/bash
else 
    exec "$@"
fi

コンテナイメージのビルド

sudo docker build ./ -t sabocl6/vscode

Dockerコンテナの起動

指定しないといけないオプションが多いため、docker-composeを使って起動します。

docker-compose.yml
version: "3.3"
services:
  devmachine:
    image: sabocla6/vscode
    volumes:
      - $HOME/.Xauthority:/root/.Xauthority
    user: "1000:1000"
    shm_size: '2G'
    network_mode: "host"
    privileged: true
    environment:
      USER: sabocla6
      PASSWD: passwd
      DISPLAY: $DISPLAY
    command: code -w
起動コマンド
sudo docker-compose up

関連記事

Docker コンテナ上でGUIアプリケーションを動かす(日本語入力)
Docker コンテナ上でGUIアプリケーションを動かす

参考記事

ユーザーの作成に関してはDockerでuid/gid指定可能かつsudo使用可能なデスクトップ環境を構築する(XRDP編)を参考にしています

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

Docker コンテナ上でGUIアプリケーションを動かす(日本語入力)

目的

Docker上でGUIアプリケーションを日本語入力可能な状態で動かします。
日本語入力しない不可の状態でのDockerイメージをベースに作成します。
Docker コンテナ上でGUIアプリケーションを動かすを参照して、コンテナイメージを作成しておいてください。

下記に関しては記載しません。

  • docker, docker-compose を導入する

日本語入力可能なコンテナを作成する

Dockerfile
FROM sabocla6/ubuntu_ui

# ***********************************************
# install packages for xrdp, and do setting
# ***********************************************
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
    language-pack-ja-base language-pack-ja fonts-noto-cjk fcitx-mozc \
    && im-config -n fcitx

# 動作確認用のGUIアプリをインストール
RUN apt-get update \
    && apt-get install -y gedit

ENV GTK_IM_MODULE=xim \
    QT_IM_MODULE=fcitx \
    XMODIFIERS=@im=fcitx \
    DefalutIMModule=fcitx

RUN locale-gen ja_JP.UTF-8  
ENV LANG=ja_JP.UTF-8 \
    LC_ALL=ja_JP.UTF-8

Dockerfileを格納しているディレクトリに移動して、下記コマンドを実行します。

Dockerイメージのビルド
sudo docker build ./ -t sabocla6/ubuntu_ui_jp

テキストエディタの起動確認

テキストエディタの起動確認
sudo docker run -v $HOME/.Xauthority:/root/.Xauthority -e DISPLAY=$DISPLAY -it --rm --network=host sabocla6/ubuntu_ui_jp gedit

テキストエディタが起動し、正常に日本語入力ができれば完了です。

関連記事

Docker上でVSCodeを動かす
Docker コンテナ上でGUIアプリケーションを動かす

参考記事

Docker コンテナ内のアプリで日本語入力をする方法

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

Docker コンテナ上でGUIアプリケーションを動かす

目的

Docker上でテキストエディタなどのGUIアプリケーションを動かせ事のできる環境を構築します。

下記に関しては別の記事にて解説します。
- 日本語入力を可能にする
- テキストエディタを導入する(VSCode)

下記に関しては記載しません。
- docker, docker-compose を導入する

UbuntuのDockerイメージへの設定追加

今後のために、下記ができるDockerイメージを作成します。
- bash-completeが有効に機能する
- ユーザー追加時にホームフォルダ内にDownloadなどの標準的なフォルダ構成が作成される

Dockerfile
FROM ubuntu

# ***********************************************
# install packages for xrdp, and do setting
# ***********************************************
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
        apt-utils sudo curl bash-completion 

# ***********************************************
# setting skelton
# ***********************************************
RUN mkdir -p /etc/skel/Desktop \
    /etc/skel/Downloads \
    /etc/skel/Templates \
    /etc/skel/Public \
    /etc/skel/Documents \
    /etc/skel/Music \
    /etc/skel/Pictures \
    /etc/skel/Videos

# ***********************************************
# bash complete 
# ***********************************************
RUN mv /etc/apt/sources.list /etc/apt/sources.list.d/sources.list

# `apt-cache --no-generate ` can not work. I don't know why.
# so, apt-cache remove option "--no-generate"
RUN sed "s/--no-generate //g" /usr/share/bash-completion/completions/apt >/tmp/apt
RUN mv /tmp/apt /usr/share/bash-completion/completions/apt


RUN { \
        echo "# enable programmable completion features (you don't need to enable"; \
        echo "# this, if it's already enabled in /etc/bash.bashrc and /etc/profile"; \
        echo "# sources /etc/bash.bashrc)."; \
        echo "if ! shopt -oq posix; then"; \
        echo "  if [ -f /usr/share/bash-completion/bash_completion ]; then"; \
        echo "    . /usr/share/bash-completion/bash_completion"; \
        echo "  elif [ -f /etc/bash_completion ]; then"; \
        echo "    . /etc/bash_completion"; \
        echo "  fi"; \
        echo "fi"; \
        echo ""; \
    } >> /root/.bashrc
コンテナイメージのビルド
sudo docker build ./ -t sabocla6/ubuntu_base 

コンテナイメージ名は好きに設定してください。
ただし、以降の記載でこのコンテナイメージをベースにコンテナイメージを作成しますので、
そのDockerfileのベースは変更してください。

GUIアプリケーション実行可能なコンテナイメージの作成

Dockerfile
FROM sabocla6/ubuntu_base

# ***********************************************
# install packages for xrdp, and do setting
# ***********************************************
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
        zenity x11-apps

# ***********************************************
# setting keyboard layout
# ***********************************************
RUN { \
      echo 'XKBMODEL="pc105"'; \
      echo 'XKBLAYOUT="jp""'; \
      echo 'XKBVARIANT=""'; \
      echo 'XKBOPTIONS=""'; \
      echo ''; \
      echo 'BACKSPACE="guess"'; \
    } > /etc/default/keyboard
コンテナイメージのビルド
sudo docker build ./ -t sabocla6/ubuntu_ui 

コンテナイメージ名は好きに設定してください。

関連記事

Docker上でVSCodeを動かす
Docker コンテナ上でGUIアプリケーションを動かす(日本語入力)

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

【Docker Network 第2章】Docker Networkingについて解説

image.png

概要

Dockerは、スタンドアロンモード、Docker Composeの使用、単一のホスト、またはコンテナーをデプロイして複数のホスト間でDockerエンジンを接続するなど、さまざまなユースケースで使用できます。 ユーザーは、デフォルトネットワーク、ホストネットワーク、またはオーバーレイなどの他のタイプのより高度なネットワークでDockerコンテナーを使用できます。 これは、ユースケースや採用されているテクノロジーによって異なります。

この記事では、さまざまなタイプのコンテナネットワークについて理解すると同時にコンテナネットワーキングについても学習します。 さまざまな種類のネットワークについて説明し、最後に、プラグインを使用してDockerネットワークを拡張する方法を理解します。 この記事はシリーズの第2部です。 第1章については、この記事をご覧ください。 また、Kubernetes NetworkingcAdvisorを使用したDockerコンテナの監視に関するリソースもありますので、興味がある方は、そちらもチェックしてみてください。

スタンドアロンのDockerネットワーク

デフォルトのブリッジネットワーク

Dockerを新たにインストールすると、デフォルトのブリッジネットワークが稼働していることがわかります。

docker network lsと入力すると、次のように表示されます。

NETWORK ID          NAME                DRIVER              SCOPE
5beee851de42        bridge              bridge              local

ifconfigコマンドを使用すると、このネットワークインターフェイスが「docker0」と呼ばれることにも気付くはずです。

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:90:68:1f:7f  txqueuelen 0  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

すべてのDockerインストールにこのネットワークがあります。 Nginxなどのコンテナを実行すると、デフォルトでブリッジネットワークに接続されます。

docker run -dit --name nginx nginx:latest

「inspect」コマンドを使用して、ネットワーク内で実行されているコンテナを確認できます。

docker network inspect bridge


---
        "Containers": {
            "dfdbc18945190c832c3e0aaa7013915d77022851e69965c134045bb3a37168c4": {
                "Name": "nginx",
                "EndpointID": "33a598ffd6d4df792c58a6b6fdc34cd162c9dd3a3f1e58add29f30ad7f1dfdac",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },

Dockerは、ソフトウェアベースのブリッジネットワークを使用します。これにより、同じブリッジネットワークに接続されているコンテナーは、同じブリッジネットワークで実行されていない他のコンテナーから分離しながら通信できます。

同じブリッジネットワークで実行されているコンテナがどのように相互に接続できるかを見てみましょう。 テスト目的で2つのコンテナを作成しましょう。

docker run -dit --name busybox1 busybox
docker run -dit --name busyboxZ busybox

コンテナのIPアドレスは次のとおりです。

docker inspect busybox1 |  jq -r  ' [0].NetworkSettings.IPAddress'
docker inspect busybox2 |  jq -r  '.[0].NetworkSettings.IPAddress'


---
172.17.0.3
172.17.0.4

これらのIPアドレスの1つを使用して、別のコンテナーからコンテナーにpingを実行してみましょう。 たとえば、IP 172.17.0.3を使用して、「busybox2」から「busybox1」という名前のコンテナにpingを実行します。

docker exec -it busybox2 ping 172.17.0.3


---
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.245 ms

したがって、同じブリッジ上のコンテナは、IPを使用して相互に認識できます。 IPの代わりにコンテナの名前を使用したい場合はどうなるでしょうか。

docker exec -it busybox2 ping busybox1
---
ping: bad address 'busybox1'

同じブリッジネットワーク上で実行されているコンテナは、IPアドレスを使用して相互に認識できることが理解できます。 一方、デフォルトのブリッジネットワークは自動サービス検出をサポートしていません。

ユーザー定義のブリッジネットワーク

Docker CLIを使用すると、他のネットワークを作成できます。 以下を使用して、2番目のブリッジネットワークを作成できます。

docker network create my_bridge --driver bridge

ここで、「busybox1」と「busybox2」を同じネットワークに接続します。

docker network connect my_bridge busybox1
docker network connect my_bridge busybox2

名前を使用して「busybox1」にpingを再試行します。

docker exec -it busybox2 ping busybox1
---
PING busybox1 (172.20.0.2): 56 data bytes
64 bytes from 172.20.0.2: seq=0 ttl=64 time=0.113 ms

自動サービス検出をサポートしているのは、ユーザー定義のブリッジネットワークのみであると結論付けることができます。 コンテナーでサービス検出を使用する必要がある場合は、デフォルトのブリッジを使用せずに、新しいブリッジを作成してください。

‍###ホストネットワーク
ホストネットワークで実行されているコンテナは、ホストのネットワーク構成と一致します。

Nginxイメージの例をとると、ポート80が公開されていることがわかります。

EXPOSE 80

コンテナを実行する場合、通常はポート80を別のポート(たとえば8080)で公開する必要があります。

docker run -dit -p 8080:80 nginx:latest

これで、コンテナはポート8080でアクセスできます。

curl -I 0.0.0.0:8080


---
HTTP/1.1 200 OK
Server: nginx/1.17.5
Date: Wed, 20 Nov 2019 22:30:31 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 22 Oct 2019 14:30:00 GMT
Connection: keep-alive
ETag: "5daf1268-264"

ホストネットワークで同じコンテナを実行すると、ホストのポート80がすべての場合に使用されるため、公開されたポートは無視されます。 実行する場合:

docker run -dit --name nginx_host --network host -p 8080:80 nginx:latest

Dockerは警告を表示します:

WARNING: Published ports are discarded when using host network mode

このコンテナを削除して、ポートを公開せずに再実行してみましょう。

docker rm -f nginx_host;
docker run -dit --name nginx_host --network host  nginx:latest

これで、ホストマシンのポート80で「curl」を実行して、Webサーバーが応答することを確認できます。

curl -I 0.0.0.0:80



---
HTTP/1.1 200 OK
Server: nginx/1.17.5
Date: Wed, 20 Nov 2019 22:32:27 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 22 Oct 2019 14:30:00 GMT
Connection: keep-alive
ETag: "5daf1268-264"
Accept-Ranges: bytes

ネットワークアドレス変換(NAT)がないため、ホストネットワークでコンテナーを実行するとパフォーマンスを最適化できます。 ホストネットワークでコンテナを実行すると、そのネットワークはホストから分離されず、独自のIPを取得しません。 これらは、このタイプのネットワークの限界です。

Macvlanネットワーク

たとえば、基盤となる物理ネットワークに直接接続されることが予想されるトラフィックを監視するアプリケーションを開発している場合は、macvlanネットワークドライバーを使用できます。 このドライバーは、各コンテナーの仮想ネットワークインターフェイスにMACアドレスを割り当てます。

例:

docker network create -d macvlan --subnet=150.50.50.50/24--gateway=150.50.50.1  -o parent=eth0 pub_net

macvlanネットワークを作成するときは、parentを指定する必要があります。これは、トラフィックが物理的にルーティングされるときに使用されるホストインターフェイスです。

None

場合によっては、コンテナを着信/発信トラフィックから分離する必要があります。ネットワークインターフェイスがないこのタイプのネットワークを使用できます。

コンテナが持つ唯一のインターフェースは、ローカルループバックインターフェース(127.0.0.1)です。

分散ネットワーク

オーバーレイネットワーク

コンテナプラットフォームには異なるホストがあり、それぞれでいくつかのコンテナが実行されている場合があります。 これらのコンテナは相互に通信する必要がある場合があります。 これは、オーバーレイネットワークが役立つ場合です。

オーバーレイネットワークは、異なるホストの複数のDockerデーモン間で作成された分散ネットワークです。 このネットワークに接続されているすべてのコンテナは通信できます。

Ingress

たとえば、Docker Swarmは、オーバーレイネットワークを使用してSwarmサービス間のトラフィックを処理します。

これをテストするために、3台のDockerマシン(manager + two machines)を作成しましょう。

docker-machine create manager
docker-machine create machine1
docker-machine create machine2

これらのマシンごとに異なるシェルを構成した後(eval $(docker-machine env を使用)、次のコマンドを使用して、managerでSwarmを初期化します。

docker swarm init --advertise-addr <IP_address>

両方のワーカーでjoinコマンドを実行することを忘れないでください。

docker swarm join --token xxxx <IP_address>:2377

docker network lsを使用して各ホスト上のネットワークを一覧表示すると、オーバーレイIngressネットワークの存在に気付くでしょう。

o5dnttidp8yq   ingress      overlay      swarm

managerで、3つのレプリカを使用して新しいサービスを作成します。

docker service create  --name  nginx --replicas 3 --publish published=8080,target=80 nginx

サービスがデプロイされているスウォームノードを確認するには、docker service psnginxを使用します。

ID                  NAME                IMAGE               NODE                DESIRED STATE       CURRENT STATE        
fmvfo2nschcq        nginx.1             nginx:latest        machine1            Running             Running 3 minutes ago
pz1kob42tqoe        nginx.2             nginx:latest        manager             Running             Running 3 minutes ago
xhhnq68sm65g        nginx.3             nginx:latest        machine2            Running             Running 3 minutes ago

この場合、各ノードでコンテナを実行しています。

docker inspect ingressを使用してIngressネットワークを検査すると、同じネットワークに接続されているピア(スワムノード)のリストを確認できます。

 "Peers": [
            {
                "Name": "3a3c4007c923",
                "IP": "192.168.99.102"
            },
            {
                "Name": "9827ad03b358",
                "IP": "192.168.99.100"
            },
            {
                "Name": "60ae1df1c8b2",
                "IP": "192.168.99.101"
            }

Ingressネットワークは、デフォルトで作成される特定のタイプのオーバーレイネットワークです。

ユーザー定義のオーバーレイネットワークに接続せずにサービスを作成すると、デフォルトでこのIngressネットワークに接続します。 Nginxを使用して、ユーザー定義のオーバーレイネットワークなしで実行されているが、デフォルトでIngressネットワークに接続されているサービスの例を次に示します。

docker service inspect nginx|jq -r  .[0].Endpoint.Ports[0]


---
{
  "Protocol": "tcp",
  "TargetPort": 80,
  "PublishedPort": 8080,
  "PublishMode": "ingress"
}

Dockerネットワークプラグイン

新しいタイプのネットワークを必要とする他のタイプのユースケースがあります。 また、別のテクノロジーを使用して、オーバーレイネットワークとVXLANトンネルを管理することもできます。

Dockerネットワークは拡張可能であり、プラグインを使用してデフォルトで提供される機能を拡張できます。

ネットワークプラグインを使用または開発できます。 DockerHubには検証済みのネットワークプラグインもいくつかあります。

image.png

各プラグインには、異なるユースケースとインストール手順があります。 たとえば、Weave Netは、ホストのクラスター全体でコンテナーを接続し、自動検出を可能にする仮想Dockerネットワークです。

これをインストールするには、DockerHubの公式の指示に従うことができます。

docker plugin install --grant-all-permissions store/weaveworks/net-plugin:2.5.2

Weave Netネットワークを作成し、以下を使用して接続可能にすることができます。

docker network create --driver=store/weaveworks/net-plugin:2.5.2 --attachable    my_custom_network

次に、同じネットワークを使用してコンテナを作成します。

docker run -dit --rm --network=my_custom_network -p 8080:80 nginx

このシリーズの3章まであります。パートIを見逃した場合は、こちらをチェックしてください。 Dockerコンテナーの監視に興味がある場合は、cAdvisorを使用したDockerの監視に関する記事でその方法を学習してください。 また、Prometheusを使用したKubernetesのモニタリングに関するブログ投稿もご覧ください。

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

Dockerでオーケストラレーションツールを使う理由

はじめに

本記事は、Dockerでなぜオーケストラレーションツールを使うのか知るための記事である。
・様々なDockerの説明で「オーケストラレーションツール」という言葉が出てくるが一体何なのか、わかりにくい。
・「オーケストラレーションツール」を理解する。

オーケストラレーションツールとは

オーケストラレーションツールは、複数のDockerを動かすためツール。

オーケストラレーションツールを使う理由

オーケストラレーションツールを使う理由を知るためには、Dockerでできないことを知ることが近道である。
Dockerは特定の環境をパッケージングして、どの環境でも動くポータビリティを保証できるツールである。
Dockerができないこと、機能としてないことは以下のものがある。

  • 複数のNodeに対してのデプロイ
  • スケーリング
  • コンテナのアップデート
  • 障害時の自動復旧
  • 負荷分散

つまり、オーケストラレーションツールを使う理由は、サービスを運用するためにはDockerの機能だけでは運用に問題が出てくる。
したがって、オーケストラレーションツールを使って提供できるようにするためにDockerとセットで使用するのである。

よく使われるオーケストラレーションツール

docker-compose

一般的に使われるオーケストラレーションツール。

swarm

クラスタリング用ツール。
Docker Compose と Docker Swarmを合わせて使う。

ECS(Elastic Container Service)

AWSが開発したオーケストレーションツール。

Kubernetes

Googleが開発したオーケストレーションツール。

おわりに

Dockerを本番のサービスで使うためには、Docker + オーケストラレーションツールを使って障害などに備えることがわかった。

Dockerの学習においては、プログラマでも必須スキルとなっているDockerだが、
本記事を加味すると、開発環境の運用ではDockerのスキルだけで問題ないが、本番のサービスを運用する段階ではオーケストラレーションツールのスキルが必要になる。
なので、プログラマに関しては Docker のスキル、インフラエンジニアに関しては Docker + オーケストラレーションツール のスキルを取得すると良いだろう。

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

Dockerでオーケストレーションツールを使う理由

はじめに

本記事は、Dockerでなぜオーケストレーションツールを使うのか知るための記事である。
・様々なDockerの説明で「オーケストレーションツール」という言葉が出てくるが一体何なのか、わかりにくい。
・「オーケストレーションツール」を理解する。

オーケストレーションツールとは

オーケストレーションツールは、複数のDockerを動かすためツール。

オーケストレーションツールを使う理由

オーケストレーションツールを使う理由を知るためには、Dockerでできないことを知ることが近道である。
Dockerは特定の環境をパッケージングして、どの環境でも動くポータビリティを保証できるツールである。
Dockerができないこと、機能としてないことは以下のものがある。

  • 複数のNodeに対してのデプロイ
  • スケーリング
  • コンテナのアップデート
  • 障害時の自動復旧
  • 負荷分散

つまり、オーケストレーションツールを使う理由は、サービスを運用するためにDockerの機能だけでは運用に問題が出てくるからである。
したがって、オーケストレーションツールを使って機能を補完して、サービスを提供できるようにするためにDockerとセットで使用するのである。

よく使われるオーケストレーションツール

docker-compose

一般的に使われるオーケストレーションツール。

swarm

クラスタリング用ツール。
Docker Compose と Docker Swarmを合わせて使う。

ECS(Elastic Container Service)

AWSが開発したオーケストレーションツール。

Kubernetes

Googleが開発したオーケストレーションツール。

おわりに

Dockerを本番のサービスで使うためには、Docker + オーケストレーションツールを使って障害などに備えることがわかった。

Dockerの学習においては、プログラマでも必須スキルとなっているDockerだが、
本記事を加味すると、開発環境の運用ではDockerのスキルだけで問題ないが、本番のサービスを運用する段階ではオーケストレーションツールのスキルが必要になる。
なので、プログラマに関しては Docker のスキル、インフラエンジニアに関しては Docker + オーケストレーションツール のスキルを取得すると良いだろう。

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

ランダム生成されるコンテナ名について

はじめに

コンテナを起動するとき、--nameを指定しないとランダムでコンテナ名がつけらえます。下記でいうところのgreat_wescoffです。

$ docker run alpine:latest

$ docker ps -a
CONTAINER ID   IMAGE           COMMAND     CREATED          STATUS                      PORTS     NAMES
0772fae09ab1   alpine:latest   "/bin/sh"   16 seconds ago   Exited (0) 15 seconds ago             great_wescoff

ふと、この名前がどのように生成されているのか気になりました。

調べ方

オープンソースなのでそれ見れば答えがわかりますが、自分なりに調べてみて最後に答え合わせを行おうと思います。

調べ方は、docker runをたくさん実行して、(ほぼ)全通りの名前のパターンを抽出し、それを眺めて法則性を見つけて行こうと思います。

$ docker run -d alpine:latest

何かしらのイメージを実行します。実行するイメージはなんでもいいのですがなるべく軽量なものを選びました。
-d オプションは、コンテナをバックグラウンドで実行してくれるコマンドです。
ですが今回はその用途でなくコンテナIDを出力するために使います。

$ docker ps -a -f "id=$cid" --format "{{.Names}}"

先ほど出力したコンテナID(cid)を用いてコンテナ名を抽出します。
-aオプションで(実行中出ないものも含めた)全てのコンテナを表示させて、
-fオプションでコンテナIDでフィルタリングを行い、
--formatで表示形式をカスタマイズします。

$ docker rm $cid

コンテナ名が抽出できたらあとは用無しなので削除します。

いざ実行

スクリプト

上記のdockerコマンドを組み合わせてshellscriptを作成します。

namesがコンテナ名のリストを格納しているファイルです。
1000件コンテナ名を取得して、1000件とも今まで蓄積してきたコンテナ名と重複してたら終了します。それまで無限ループします。

total=0
while true; do

    for i in `seq 1000`; do
        cid=$(docker run -d alpine:latest)
        docker ps -a -f "id=$cid" --format "{{.Names}}" >> names
        docker rm $cid > /dev/null
    done

    sort -u names -o names
    after_wc=$(cat names | wc -l | tr -d ' ')

    if [ "$total" = "$after_wc" ]; then
        exit
    else
        echo "continue (find new name: $(($after_wc-$total)))"
        total=$after_wc
    fi

done

1日後、、、

処理が終わっていなかったので、少し高速化することにしました。一応この時点で、1エポックごとに新名が500件ほどに下がってきていたので、どこかで頭打ちにはなりそうです。

やはりdockerコマンドを実行している部分がネックなので、ある程度並列実行させることにしました。

total=0

get_name() {
    for i in `seq 100`; do
        cid=$(docker run -d alpine:latest)
        docker ps -a -f "id=$cid" --format "{{.Names}}" >> names
        docker rm $cid > /dev/null
    done
}
export -f get_name

while true; do

    seq 10 | xargs -I ZZ -P 10 sh -c get_name

    sort -u names -o names
    after_wc=$(cat names | wc -l | tr -d ' ')

    if [ "$total" = "$after_wc" ]; then
        exit
    else
        echo "continue (find new name: $(($after_wc-$total)))"
        total=$after_wc
    fi

done

名前を取得する部分を関数化させて10並列で実行させます。並列数は多ければ処理も高速化できることになりますが、PCスペックの関係か以下のエラーが頻出して、最悪の場合だとdockerが機能しなくなってしまいました。

Error response from daemon: You cannot remove a running container 54161ca2bea3d750a3e873a329a760af990dfcc115cb13ecec322cb2f3eff85a. Stop the container before attempting removal or force remove
ERRO[0003] error waiting for container: context canceled

100回繰り返しを10並列にしたこのバージョンでもたまに発生します。

2日後、、、

結局このループは終わりませんでしたが、1エポックごとに新名が10個ほどしか見つからなくなってきたので、打ち切りました。ここで法則性を見つけていきます。

解析

仰々しく解析などといっていますが、抽出されたコンテナ名を眺めてこんな感じの法則ありそう、と考えるだけです。

見つかった名前の数は25422個。これにあと数百個は見つかっていない名前がありそうです。名前には、必ずアンダーバー(_)が入っていて、前後の単語を区切る文字のようです。この単語をリストアップしてみます。また、前後でこの単語は重複していないようですので、別々にリストアップします。

sed -e 's/_.*//g' names > names_first
uniq names_first names_first_uniq


admiring
adoring
affectionate
agitated
amazing
angry
awesome
beautiful
blissful
bold
boring
brave
busy
charming
clever
compassionate
competent
condescending
confident
cool
cranky
crazy
dazzling
determined
distracted
dreamy
eager
ecstatic
elastic
elated
elegant
eloquent
epic
exciting
fervent
festive
flamboyant
focused
friendly
frosty
funny
gallant
gifted
goofy
gracious
great
happy
hardcore
heuristic
hopeful
hungry
infallible
inspiring
intelligent
interesting
jolly
jovial
keen
kind
laughing
loving
lucid
magical
modest
musing
mystifying
naughty
nervous
nice
nifty
nostalgic
objective
optimistic
peaceful
pedantic
pensive
practical
priceless
quirky
quizzical
recursing
relaxed
reverent
romantic
sad
serene
sharp
silly
sleepy
stoic
strange
stupefied
suspicious
sweet
tender
thirsty
trusting
unruffled
upbeat
vibrant
vigilant
vigorous
wizardly
wonderful
xenodochial
youthful
zealous
zen

後方の単語はソートもしないといけないので、上記の抽出スクリプトで使っていたコマンドを流用。

sed -e 's/.*_//g' names > names_second
sort -u names_second -o names_second_uniq


agnesi
albattani
albattani2
allen
allen7
almeida
antonelli
antonelli6
archimedes
archimedes0
archimedes3
ardinghelli
aryabhata
aryabhata6
austin
austin3
babbage
banach
banzai
bardeen
bartik
bassi
bassi0
bassi2
beaver
bell
benz
benz9
bhabha
bhaskara
black
black0
blackburn
blackburn3
blackwell
bohr
booth
booth6
borg
bose
bose2
bose6
bouman
boyd
boyd4
brahmagupta
brahmagupta3
brahmagupta4
brattain
brattain8
brown
buck
burnell
burnell4
cannon
cannon3
cannon7
carson
carson8
cartwright
carver
cerf
chandrasekhar
chaplygin
chatelet
chatelet8
chatterjee
chaum
chebyshev
clarke
cohen
colden
colden4
cori
cray
cray5
curie
curie9
curran
curran2
darwin
darwin8
davinci
davinci3
davinci7
dewdney
dewdney1
dhawan
diffie
dijkstra
dijkstra4
dijkstra6
dirac
driscoll
driscoll1
dubinsky
easley
edison
einstein
elbakyan
elgamal
elion
elion8
ellis
engelbart
euclid
euclid4
euler
euler0
faraday
faraday5
feistel
feistel9
fermat
fermat2
fermi
fermi5
feynman
feynman2
franklin
gagarin
galileo
galois
ganguly
gates
gauss
germain
goldberg
goldstine
goldstine5
goldstine9
goldwasser
goldwasser9
golick
golick7
goodall
gould
greider
greider1
grothendieck
haibt
hamilton
haslett
haslett5
hawking
hawking7
heisenberg
hellman
hellman1
hermann
herschel
hertz
heyrovsky
heyrovsky0
hodgkin
hodgkin5
hofstadter
hofstadter7
hoover
hoover2
hopper
hugle
hypatia
ishizaka
jackson
jang
jemison
jennings
jennings9
jepsen
jepsen7
jepsen8
johnson
joliot
jones
jones2
jones7
kalam
kalam6
kapitsa
kare
kare8
keldysh
keldysh0
keller
kepler
kepler8
khayyam
khayyam5
khayyam9
khorana
kilby
kilby0
kirch
knuth
knuth5
kowalevski
lalande
lalande5
lamarr
lamarr8
lamport
leakey
leavitt
leavitt1
lederberg
lehmann
lewin
lichterman
liskov
lovelace
lumiere
lumiere1
mahavira
margulis
matsumoto
matsumoto9
maxwell
maxwell4
maxwell8
mayer
mccarthy
mcclintock
mclaren
mclaren2
mclaren5
mclean
mclean7
mcnulty
mcnulty8
meitner
mendel
mendeleev
meninsky
meninsky3
merkle
mestorf
mirzakhani
montalcini
montalcini7
moore
moore0
morse
moser
murdock
murdock4
napier
nash
nash2
neumann
newton
nightingale
nobel
noether
noether6
northcutt
noyce
panini
pare
pascal
pascal3
pasteur
payne
perlman
perlman3
pike
poincare
poitras
poitras3
proskuriakova
ptolemy
ptolemy6
raman
ramanujan
rhodes
ride
ride5
ritchie
robinson
roentgen
rosalind
rubin
saha
sammet
sammet4
sanderson
satoshi
shamir
shannon
shaw
shaw4
shirley
shockley
shtern
shtern1
sinoussi
snyder
solomon
solomon5
solomon7
spence
stonebraker
sutherland
swanson
swanson5
swartz
swartz6
swirles
taussig
tereshkova
tesla
tesla4
tharp
tharp0
thompson
thompson7
torvalds
torvalds7
tu
turing
varahamihira
vaughan
villani
visvesvaraya
visvesvaraya0
visvesvaraya3
volhard
volhard4
wescoff
wescoff1
wilbur
wilbur6
wilbur9
wiles
williams
williams1
williamson
wilson
wilson9
wing
wozniak
wozniak2
wright
wright5
wu
wu1
yalow
yalow0
yonath
zhukovsky

まだ出現していない単語がないとして、これらの108個×350個の単語を組み合わせてコンテナ名は作られているのでないかと推測します。

そうなると、組み合わせは37800個になりますので、スクリプトも非効率で試行回数が足りていなかったかなと反省です。

答え合わせ

上記で抽出した単語を頼りに、ソースコードを追いました。

https://github.com/moby/moby/blob/master/pkg/namesgenerator/names-generator.go

大枠は捉えられていたようですが、予想と違いました。108個×237個の単語の組み合わせと、引数として与えられるリトライ数によっては、後ろにランダムで0~9の数字が付与されるでした。
(ただし、boringwozniakの組み合わせはのぞく)

これを受けて、私が抽出した350個の後方の単語のうち数字が付与されているものを除くとピッタリ237個になります。つまり候補の単語は前後全て抽出できていたようです。

しかし、ランダムで付与される数字も含めて、理論上の組み合わせの総数は(108*237-1)*11=281545となり(しかも数字が付与される確率自体が低そう)、途方もないので打ち切って正解でした。

以上になります。ふと気になったことではありますが、調べているうちに(特にshellについて)勉強になることが多くなんだかんだ有意義な調査でした。

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

docker-composeでdjangoからmysqlコンテナに繋がらなかったのを何とか解決してみた時の話

djangoの開発環境をDockerで作ろうとしたところ、どうしても一つだけうまくいかなかったのがdjangoからmysqlへ接続するところでした。

かれこれ3日くらいずっと悩まされ続けたのがこれです。。

django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'mysql' (11001)")

色々問題を切り分けてみて、mysqlコンテナのIPの名前解決はうまくいってそうだし、portsとexposeの部分も特にミスっていないし、、とすると問題はMySQLコンテナ内に入った後の挙動。

日本語のサイトにはいい情報が見つからなかったのですが、英語のドキュメントを色々あさっているうちにようやく解決できたのでまとめてみました。

環境

  • Windows 10
  • Docker for Windows

前提

  • 既にpythonコンテナの中に入ってDjangoのプロジェクトを生成していること

ディレクトリ構成

proj/
  ├ docker/
  │   ├ nginx/
  │   │  └ default.conf
  │   └ python/
  │      ├ Dockerfile
  │      └ requirements.txt
  ├ django_proj (以下略)
  ├ docker-compose.yml
  └ manage.py

方法

docker-compose.ymlのmysqlの設定に注意!(それだけ!でした。笑)

docker-compose.yml
version: "3.9"

services:
  python:
    build: ./docker/python
    command: gunicorn composeexample.wsgi:application --bind 0.0.0.0:8000 --reload
    volumes:
      - .:/code
    expose:
      - "8000"

  nginx:
    image: nginx:1.19
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./static:/etc/nginx/static
    ports:
      - "1337:80"
    depends_on:
      - python

  mysql:
    image: mysql:5.6
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./docker/db/data:/var/lib/mysql
    expose:
      - "3306"
    environment:
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_ROOT_HOST=%           # この1行が今回のポイントでした

  phpmyadmin:
    image: phpmyadmin
    ports:
      - "8080:80"
    environment:
      - PMA_ARBITRARY=1

MySQL公式ページに以下の記載がありました。

MYSQL_ROOT_HOST: By default, MySQL creates the 'root'@'localhost' account. This account can only be connected to from inside the container as described in Connecting to MySQL Server from within the Container. To allow root connections from other hosts, set this environment variable. For example, the value 172.17.0.1, which is the default Docker gateway IP, allows connections from the host machine that runs the container. The option accepts only one entry, but wildcards are allowed (for example, MYSQL_ROOT_HOST=172...* or MYSQL_ROOT_HOST=%).

デフォルトではroot@localhostでアカウントを作ってしまうので、rootユーザーとして接続できるのはlocalhost、すなわちdockerコンテナ内からのみとなってしまうようです。

なので、MYSQL_ROOT_HOST=%の記述を追加しておけば、どのIPアドレスからもrootユーザーとしてログインできるようになるので、違うコンテナからの接続も受け付けられるということなんだと思います。(たぶん)

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

docker-composeでDjangoからMysqlコンテナに繋がらなかったのを何とか解決してみた時の話

Djangoの開発環境をDockerで作ろうとしたところ、どうしても一つだけうまくいかなかったのがDjangoからMysqlへログインするところでした。

かれこれ3日くらいずっと悩まされ続けたのがこれです。。

django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'mysql' (11001)")

色々問題を切り分けてみて、mysqlコンテナのIPの名前解決はうまくいってそうだし、portsとexposeの部分も特にミスっていないし、、とすると問題はMySQLコンテナ内に入った後の挙動。

日本語のサイトにはいい情報が見つからなかったのですが、英語のドキュメントを色々あさっているうちにようやく解決できたのでまとめてみました。

環境

  • Windows 10
  • Docker for Windows

前提

  • 既にpythonコンテナの中に入ってDjangoのプロジェクトを生成していること

ディレクトリ構成

proj/
  ├ docker/
  │   ├ nginx/
  │   │  └ default.conf
  │   └ python/
  │      ├ Dockerfile
  │      └ requirements.txt
  ├ django_proj (以下略)
  ├ docker-compose.yml
  └ manage.py

方法

docker-compose.ymlのmysqlの設定に注意!(それだけ!でした。笑)

docker-compose.yml
version: "3.9"

services:
  python:
    build: ./docker/python
    command: gunicorn composeexample.wsgi:application --bind 0.0.0.0:8000 --reload
    volumes:
      - .:/code
    expose:
      - "8000"

  nginx:
    image: nginx:1.19
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./static:/etc/nginx/static
    ports:
      - "80:80"
    depends_on:
      - python

  mysql:
    image: mysql:5.6
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./docker/db/data:/var/lib/mysql
    expose:
      - "3306"
    environment:
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_ROOT_HOST=%           # この1行が今回のポイントでした

  phpmyadmin:
    image: phpmyadmin
    ports:
      - "8080:80"
    environment:
      - PMA_ARBITRARY=1

MySQL公式ページに以下の記載がありました。

MYSQL_ROOT_HOST: By default, MySQL creates the 'root'@'localhost' account. This account can only be connected to from inside the container as described in Connecting to MySQL Server from within the Container. To allow root connections from other hosts, set this environment variable. For example, the value 172.17.0.1, which is the default Docker gateway IP, allows connections from the host machine that runs the container. The option accepts only one entry, but wildcards are allowed (for example, MYSQL_ROOT_HOST=172...* or MYSQL_ROOT_HOST=%).

デフォルトではroot@localhostでアカウントを作ってしまうので、rootユーザーとしてログインできるのはlocalhost、すなわちdockerコンテナ内からのみとなってしまうようです。

なので、MYSQL_ROOT_HOST=%の記述を追加しておけば、どのIPアドレスからもrootユーザーとしてログインできるようになるので、違うコンテナからのログインも受け付けられるということなんだと思います。(たぶん)

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

docker-composeでDjangoからMysqlに繋がらない

Djangoの開発環境をDockerで作ろうとしたところ、どうしても一つだけうまくいかなかったのがDjangoからMysqlへログインするところでした。

かれこれ3日くらいずっと悩まされ続けたのがこれです。。

django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'mysql' (11001)")

色々問題を切り分けてみて、mysqlコンテナのIPの名前解決はうまくいってそうだし、portsとexposeの部分も特にミスっていないし、、とすると問題はMySQLコンテナ内に入った後の挙動。

日本語のサイトにはいい情報が見つからなかったのですが、英語のドキュメントを色々あさってようやく解決できたのでまとめてみました。

環境

  • Windows 10
  • Docker for Windows

前提

  • 既にpythonコンテナの中に入ってDjangoのプロジェクトを生成していること

ディレクトリ構成

proj/
  ├ docker/
  │   ├ nginx/
  │   │  └ default.conf
  │   └ python/
  │      ├ Dockerfile
  │      └ requirements.txt
  ├ django_proj (以下略)
  ├ docker-compose.yml
  └ manage.py

解決方法

docker-compose.ymlのmysqlの設定に注意!(それだけ!でした。笑)

docker-compose.yml
version: "3.9"

services:
  python:
    build: ./docker/python
    command: gunicorn composeexample.wsgi:application --bind 0.0.0.0:8000 --reload
    volumes:
      - .:/code
    expose:
      - "8000"

  nginx:
    image: nginx:1.19
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./static:/etc/nginx/static
    ports:
      - "80:80"
    depends_on:
      - python

  mysql:
    image: mysql:5.6
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./docker/db/data:/var/lib/mysql
    expose:
      - "3306"
    environment:
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_ROOT_HOST=%           # この1行が今回のポイントでした

  phpmyadmin:
    image: phpmyadmin
    ports:
      - "8080:80"
    environment:
      - PMA_ARBITRARY=1

MySQL公式ページに以下の記載がありました。

MYSQL_ROOT_HOST: By default, MySQL creates the 'root'@'localhost' account. This account can only be connected to from inside the container as described in Connecting to MySQL Server from within the Container. To allow root connections from other hosts, set this environment variable. For example, the value 172.17.0.1, which is the default Docker gateway IP, allows connections from the host machine that runs the container. The option accepts only one entry, but wildcards are allowed (for example, MYSQL_ROOT_HOST=172...* or MYSQL_ROOT_HOST=%).

デフォルトではroot@localhostでアカウントを作ってしまうので、rootユーザーとしてログインできるのはlocalhost、すなわちdockerコンテナ内からのみとなってしまうようです。

なので、MYSQL_ROOT_HOST=%の記述を追加しておけば、どのIPアドレスからもrootユーザーとしてログインできるようになるので、違うコンテナからのログインも受け付けられるということなんだと思います。(たぶん)

参考

https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/docker-mysql-more-topics.html#docker_var_mysql-root-host

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

docker-compose使用時にDjangoからMySQLにログインできない

Djangoの開発環境をDockerで作ろうとしたところ、どうしても一つだけうまくいかなかったのがDjangoからMySQLへログインするところでした。

かれこれ3日くらいずっと悩まされ続けたのがこれです。。

django.db.utils.OperationalError: (2005, "Unknown MySQL server host 'mysql' (11001)")

色々問題を切り分けてみて、mysqlコンテナのIPの名前解決はうまくいってそうだし、portsとexposeの部分も特にミスっていないし、、とすると問題はMySQLコンテナ内に入った後の挙動。

日本語のサイトにはいい情報が見つからなかったのですが、英語のドキュメントを色々探してようやく解決できたのでまとめてみました。

環境

  • Windows 10
  • Docker for Windows

前提

  • 既にpythonコンテナの中に入ってDjangoのプロジェクトを生成していること

ディレクトリ構成

proj/
  ├ docker/
  │   ├ nginx/
  │   │  └ default.conf
  │   └ python/
  │      ├ Dockerfile
  │      └ requirements.txt
  ├ django_proj (以下略)
  ├ docker-compose.yml
  └ manage.py

解決方法

docker-compose.ymlのmysqlの設定に注意!(それだけ!でした。笑)

docker-compose.yml
version: "3.9"

services:
  python:
    build: ./docker/python
    command: gunicorn composeexample.wsgi:application --bind 0.0.0.0:8000 --reload
    volumes:
      - .:/code
    expose:
      - "8000"

  nginx:
    image: nginx:1.19
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./static:/etc/nginx/static
    ports:
      - "80:80"
    depends_on:
      - python

  mysql:
    image: mysql:5.6
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    volumes:
      - ./docker/db/data:/var/lib/mysql
    expose:
      - "3306"
    environment:
      - MYSQL_ROOT_USER=root
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_ROOT_HOST=%           # この1行が今回のポイントでした

  phpmyadmin:
    image: phpmyadmin
    ports:
      - "8080:80"
    environment:
      - PMA_ARBITRARY=1

MySQL公式ページに以下の記載がありました。

MYSQL_ROOT_HOST: By default, MySQL creates the 'root'@'localhost' account. This account can only be connected to from inside the container as described in Connecting to MySQL Server from within the Container. To allow root connections from other hosts, set this environment variable. For example, the value 172.17.0.1, which is the default Docker gateway IP, allows connections from the host machine that runs the container. The option accepts only one entry, but wildcards are allowed (for example, MYSQL_ROOT_HOST=172...* or MYSQL_ROOT_HOST=%).

デフォルトではroot@localhostでアカウントを作ってしまうので、rootユーザーとしてログインできるのはlocalhost、すなわちdockerコンテナ内からのみとなってしまうようです。

なので、MYSQL_ROOT_HOST=%の記述を追加しておけば、どのIPアドレスからもrootユーザーとしてログインできるようになるので、違うコンテナからのログインも受け付けられるということなんだと思います。(たぶん)

参考

https://dev.mysql.com/doc/mysql-installation-excerpt/8.0/en/docker-mysql-more-topics.html#docker_var_mysql-root-host

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