2019年10月7日 星期一

docker 心得2019

系統:CentOS 7.6

安裝docker CE

由於 Docker 後來分為 Docker EE(Enterprise Edition)與 Docker CE(Community Edition)兩種版本,新的套件名稱與舊的不同,所以在安裝 Docker 之前,要先移除 CentOS Linux 系統上舊版的 Docker 套件:(新系統可略)
# yum remove docker docker-common container-selinux docker-selinux docker-engine docker-engine-selinux

安裝一些必要套件:
# yum install -y yum-utils device-mapper-persistent-data lvm2

新增 Docker 官方的 stable 套件庫(repository):
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

安裝 Docker CE 版:
# yum install docker-ce

將你的用戶加入docker group (實測該用戶還是不能執行docker  重啟機器打開新的screen才生效)
$ sudo usermod -aG docker $(whoami)
執行後可檢查 /etc/gshadow 和 /etc/group

docker 開機自動啟動
# systemctl enable docker.service

開啟docker 服務
# systemctl start docker.service

測試
# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:b8ba256769a0ac28dd126d584e0a2011cd2877f3f76e093a7ae560f2a5301c00
Status: Downloaded newer image for hello-world:latest
之後docker images 會多一個 hello-world:latest 的鏡像

安裝Docker Compose

安裝 epel
# yum install epel-release

查裝什麼package才能用pip
# yum provides */pip

安裝pip
# yum install python34-pip

安裝docker compose
# pip3.4 install docker-compose
...
You are using pip version 8.1.2, however version 19.2.3 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

升級pip
# pip3.4 install --upgrade pip
...
Successfully installed pip-19.2.3


檢測pip版本(升級後pip可以直接用了)
# pip --version
pip 19.2.3 from /usr/lib/python3.4/site-packages/pip (python 3.4)


升級Python packages,讓docker-compose 正確執行(我沒做)
# yum upgrade python*

查 docker-compose 版本
# docker-compose version
docker-compose version 1.24.1, build 4667896
docker-py version: 3.7.3
CPython version: 3.4.10

安裝Docker Compose - 方法2

如果pip安裝遇到 RuntimeError: Python 3.5 or later is required 錯誤,可使用這個方法。更無腦
https://phoenixnap.com/kb/install-docker-compose-centos-7  How To Install Docker Compose On CentOS 7
# curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose

如果報錯:
curl: (35) Peer reports incompatible or unsupported protocol version.
https://blog.csdn.net/feinifi/article/details/79629904  git clone 报错:Peer reports incompatible or unsupported protocol version解决办法
原因是curl,nss的版本低

解法:

# yum update nss curl



docker-compose 自動完成

# curl -L https://raw.githubusercontent.com/docker/compose/1.25.4/contrib/completion/bash/docker-compose -o /etc/bash_completion.d/docker-compose
讓安裝前的tty  docker-compose可以自動完成
# . /etc/bash_completion.d/docker-compose

開啟ipv4 ip_forward

啟動時如果報錯
# docker run -d --name my-running-app -p 5656:80 -v /root/php5.6-apache/src:/var/www/html my-php-app:latest
WARNING: IPv4 forwarding is disabled. Networking will not work.
b44f4990a94025f7d03329dfb32c64b2677dc595d937a309582150b409c0404a

https://stackoverflow.com/questions/41453263/docker-networking-disabled-warning-ipv4-forwarding-is-disabled-networking-wil Docker Networking Disabled: WARNING: IPv4 forwarding is disabled. Networking will not work
https://blog.csdn.net/weiguang1017/article/details/76212203 centos 7 Docker容器启动报WARNING: IPv4 forwarding is disabled. Networking will not work
https://carlislebear.blogspot.com/2014/11/arch-linux-internet-sharing.html  Arch Internet sharing(透過另一台電腦上網)
Windows是無法訪問容器的web服務的(hyper-v上可以),要開啟以下設定
/etc/sysctl.conf
net.ipv4.ip_forward=1
重啟網路
# systemctl restart network
這樣windows才能訪問容器的web服務
如果打不開,要注意有沒有因為被XDebug斷住了所以打不開

laradock

重啟Exited 的 laradock container

# docker ps -a
CONTAINER ID        IMAGE                COMMAND                  CREATED             STATUS                      PORTS                                        NAMES
cc866de06b61        laradock_nginx       "/bin/bash /opt/star…"   2 months ago        Exited (255) 11 days ago    0.0.0.0:443->443/tcp, 0.0.0.0:5566->80/tcp   laradock_ngin
x_1
ce974cde40bf        laradock_php-fpm     "docker-php-entrypoi…"   3 months ago        Exited (255) 11 days ago    9000/tcp                                     laradock_php-
fpm_1
cb36fbf53996        laradock_workspace   "/sbin/my_init"          3 months ago        Exited (255) 11 days ago    0.0.0.0:2222->22/tcp                         laradock_work
space_1
d475c0f6d18f        docker:dind          "dockerd-entrypoint.…"   3 months ago        Exited (255) 11 days ago    2375-2376/tcp                                laradock_dock
er-in-docker_1
64c1a5ed1659        laradock_mysql       "docker-entrypoint.s…"   3 months ago        Exited (255) 2 months ago   0.0.0.0:3306->3306/tcp, 33060/tcp            laradock_mysq
l_1

啟動單一容器

# docker start laradock_workspace_1
laradock_workspace_1

但因為laradock 是很多容器組合而成的

正確的重啟laradock

# docker-compose up -d workspace nginx
laradock_docker-in-docker_1 is up-to-date
laradock_workspace_1 is up-to-date
Starting laradock_php-fpm_1 ... done
Starting laradock_nginx_1   ... done

如果報錯:
Creating network "laradock_frontend" with driver "bridge"
ERROR: Failed to Setup IP tables: Unable to enable SKIP DNAT rule:  (iptables failed: iptables --wait -t nat -I DOCKER -i br-7d0b53dc35e0 -j RETURN: iptables: No chain/target/match by that name.
 (exit status 1))
原因:
應該是改過防火墻iptables造成的
https://stackoverflow.com/a/53766860  iptables: No chain/target/match error (with docker network create)
https://github.com/wodby/docker4drupal/issues/211#issuecomment-351016274  Unable to enable SKIP DNAT rule (未使用)
解法:
重啟docker
# systemctl restart docker
再重啟laradock
# docker-compose up -d workspace nginx

進入workspace容器

# docker exec -it laradock_workspace_1 bash
上面是以root身份進入,跑composer 會有警告。如何進入容器跑composer不報警告?
以laradock身份進入容器
# docker-compose exec --user=laradock workspace bash
laradock@daa4f318e534:/var/www$ composer --version
Composer version 1.9.0 2019-08-02 20:55:32


關閉laradock

# docker-compose down

多人開發

配置.env

#   APP_CODE_PATH_HOST=../  
# APP_CODE_PATH_HOST=../project-z/coolapp/   # 使用 laradock/nginx/sites/default.conf 不需特別設定
APP_CODE_PATH_HOST=../project-z/  # 多個專案,複製 laradock/nginx/sites/app.conf.example 成 coolapp.conf 和 coolapp2.conf
#   WORKSPACE_INSTALL_XDEBUG=false
WORKSPACE_INSTALL_XDEBUG=true
#   PHP_FPM_INSTALL_XDEBUG=false
PHP_FPM_INSTALL_XDEBUG=true  # workspace 和 php-fpm容器都裝XDebug
#   NGINX_HOST_HTTP_PORT=80
NGINX_HOST_HTTP_PORT=5566


coolapp.conf

root /var/www/app;  => root /var/www/coolapp/public;

coolapp2.conf

server_name app.test; => server_name app2.test;
root /var/www/app;  => root /var/www/coolapp2/public;

windows設hosts,重啟laradock(down 和 up),然後 http://app.test:5566/ 訪問coolapp,http://app2.test:5566/ 訪問 coolapp2

更新laradock

git pull 更新laradock後重新build會報錯,因為env-example 已經被改過了,加了一些配置
先備份自己的.env(要記得你改了什麼),然後cp env-example .env 然後再把你原本在.env改的配置改到新的.env。這樣build才會成功

php安裝memcache

修改.env
#   PHP_FPM_INSTALL_MEMCACHED=false
PHP_FPM_INSTALL_MEMCACHED=true

需重新build php-fpm容器出錯

# docker-compose build php-fpm
...
E: Failed to fetch http://deb.debian.org/debian/pool/main/c/cups/libcupsimage2_2.2.10-6+deb10u1_amd64.deb  404  Not Found [IP: 151.101.10.133 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
ERROR: Service 'php-fpm' failed to build: The command '/bin/sh -c if [ ${INSTALL_IMAGEMAGICK} = true ]; then     apt-get install -y libmagickwand-dev imagemagick &&     pecl install imagick &&     docker-php-ext-enable imagick ;fi' returned a non-zero code: 100
build 失敗
https://github.com/laradock/laradock/issues/2434
https://blog.51cto.com/beijing0414/1633956 
原來是hyper-v 系統的時間錯誤(當天應為4/8)
[root@localhost laradock]# date
Mon Apr  6 00:06:11 -02 2020
解法:
先安裝ntpdate
# yum install ntpdate
[root@localhost laradock]# date
Mon Apr  6 00:36:28 -02 2020
[root@localhost laradock]# ntpdate cn.pool.ntp.org
 8 Apr 13:07:13 ntpdate[14154]: step time server 119.28.206.193 offset 217834.861195 sec
[root@localhost laradock]# date
Wed Apr  8 13:07:15 -02 2020

重新build php-fpm(不吃緩存,比較慢)
# docker-compose build --no-cache php-fpm
# docker-compose up --build  // 不要不指定service,否則會全部build

這樣phpinfo()和命令行php -m 才有memcached

安裝docker-machine (無使用)

# base=https://github.com/docker/machine/releases/download/v0.16.0 &&
  curl -L $base/docker-machine-$(uname -s)-$(uname -m) >/tmp/docker-machine &&
  sudo mv /tmp/docker-machine /usr/local/bin/docker-machine &&
  chmod +x /usr/local/bin/docker-machine

檢視配置檔案位於哪裡

https://codertw.com/%E4%BC%BA%E6%9C%8D%E5%99%A8/160314/
$ systemctl show --property=FragmentPath docker
FragmentPath=/usr/lib/systemd/system/docker.service

開啟docker API

https://gist.github.com/styblope/dc55e0ad2a9848f2cc3307d4819d819f
新增文件:/etc/docker/daemon.json
{"hosts": ["tcp://0.0.0.0:2375", "unix:///var/run/docker.sock"]}
新增文件:/etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd
重新加載 systemd daemon
# systemctl daemon-reload
重啟docker
# systemctl restart docker.service
在機器上測試
$ curl http://localhost:2375
{"message":"page not found"}
但是windows上打不開 => server要打開 2375 端口
# firewall-cmd --zone=public --add-port=2375/tcp --permanent
# firewall-cmd --reload
然後在Windows 瀏覽器上直接打開 http://192.168.1.9:2375/info 顯示json即成功

忽然進不了XDebug斷點

commit ab4e06f270ae83d6e41702b2b652a980b12816ce
Author: Jordy Schreuders <3071062+99linesofcode@users.noreply.github.com>
Date:   Fri Feb 14 15:15:04 2020 +0100

    Default to host.docker.internal

因為更新重新build php-fpm後這個commit把 xdebug.remote_connect_back 改成0了
修改 php-fpm/xdebug.ini 、 workspace/xdebug.ini 將 xdebug.remote_connect_back 改回1,然後重新build
# docker-compose build php-fpm
ps. 重新build 時間比較久,改 xdebug.ini 後沒法像  nginx/sites/default.conf 只需要重啟laradock就能生效,必須build

進不了XDebug斷點-2

新hyper-v虛擬機上裝的laradock,在windows本機不要用同一個PHPStorm 專案改deployment去連,會一直進不了斷點,開一個新project後重新設deployment,請求接口和cli時會自動匹配,PHP CLI無需設docker。不要在同一個PHPStorm projcet上折騰
實體開發機裝了兩個PHP(php 5.5 + 7.3),上面的laradock http能進xdebug,但是cli不行 => php7.3改用hyper-v的laradock去斷點

進不了XDebug斷點-3

如果laradock中 http請求可以斷點,但是CLI不能斷點。別折騰了,直接在hyper-v上面裝PHP去做CLI斷點,不一定要在laradock中斷點。
檢查:
使用-d 自定義INI條目
$ php -dxdebug.remote_enable=1 -dxdebug.remote_mode=req -dxdebug.remote_port=9000 -dxdebug.remote_host=192.168.1.7 -dxdebug.remote_connect_back=0 -dxdebug.idekey=PHPSTORM public/index.php

要注意 xdebug.remote_enable=1 是否開啟

其實是 laradock 的 workspace 容器的xdebug 版本是3.0.0這個原因造成的,workspace和php-fpm容器裝的是不同的xdebug,workspace負責cli,php-fpm負責網頁,所以網頁上的phpinfo()查到的是是php-fpm的xdebug版本,而workspace的xdebug版本要在容器裡cli執行,如:
root@e7aa5f3bd006:/var/www# php -r 'phpinfo();' | grep Xdebug
    with Xdebug v2.5.5, Copyright (c) 2002-2017, by Derick Rethans
需要改 workspace/Dockerfile 的 xDebug 部分,讓workspcace 容器安裝低版本的xdebug

laradock中websocket 端口對外

https://github.com/laradock/laradock/issues/2002#issuecomment-468884705
編輯 docker-compose.yml 加入
services:
  workspace:
    port:
      - 2346:2346
然後重啟laradock



和gitlab端口衝突

目前已知 8080 和3000端口會和gitlab衝突(gitlab已開啟)

解法:

https://github.com/laradock/laradock/issues/2512#issuecomment-589719158  Bind for 0.0.0.0:8080 failed: port is already allocated

換一個端口,修改.env
WORKSPACE_VUE_CLI_SERVE_HOST_PORT=8080 => 8084
...
WORKSPACE_BROWSERSYNC_HOST_PORT=3000 => 3002

安裝特定版本的xdebug

如果你的專案和xdebug最新版本(3.0.0+)有衝突
https://bugs.xdebug.org/view.php?id=1883  0001883: Function xdebug_is_enabled has been removed
XDebug 3.0.0beta1版本把 xdebug_is_enabled() 移除了
可以這樣做
diff --git a/php-fpm/Dockerfile b/php-fpm/Dockerfile
index 1837b45..a64bf63 100644
--- a/php-fpm/Dockerfile
+++ b/php-fpm/Dockerfile
@@ -193,7 +193,7 @@ RUN if [ ${INSTALL_XDEBUG} = true ]; then \
     if [ $(php -r "echo PHP_MINOR_VERSION;") = "0" ]; then \
       pecl install xdebug-2.9.0; \
     else \
-      pecl install xdebug; \
+      pecl install xdebug-2.9.8; \
     fi \
   fi && \
   docker-php-ext-enable xdebug \
ps. PHP_MINOR_VERSION就是PHP的中版本號,ex. php 7.3,PHP_MINOR_VERSION就是3

因為改了Dockerfile,所以要重新build,雖然有緩存,但還是有點久
$ docker-compose build php-fpm
...
Step 29/159 : RUN if [ ${INSTALL_XDEBUG} = true ]; then   if [ $(php -r "echo PHP_MAJOR_VERSION;") = "5" ]; then     pecl install xdebug-2.5.5;   else     if [ $(php -r "echo PHP_MINOR_VERSION;") = "0" ]; then       pecl install xdebug-2.9.0;     else       pecl install xdebug-2.9.8;     fi   fi &&   docker-php-ext-enable xdebug ;fi
 ---> Running in 999878a0db51
downloading xdebug-2.9.8.tgz ...
Starting to download xdebug-2.9.8.tgz (245,293 bytes)
...................................................done: 245,293 bytes
91 source files, building
running: phpize
Configuring for:
PHP Api Version:         20180731
Zend Module Api No:      20180731
Zend Extension Api No:   320180731
building in /tmp/pear/temp/pear-build-defaultusergNFJEA/xdebug-2.9.8
running: /tmp/pear/temp/xdebug/configure --with-php-config=/usr/local/bin/php-config
checking for grep that handles long lines and -e... /bin/grep

自定義workspace中的.bashrc

由 workspace/Dockerfile 
COPY ./aliases.sh /home/laradock/aliases.sh
...
USER laradock
RUN echo "" >> ~/.bashrc && \
    echo "# Load Custom Aliases" >> ~/.bashrc && \
    echo "source ~/aliases.sh" >> ~/.bashrc && \
      echo "" >> ~/.bashrc

修改 workspace/aliases.sh 可以客製化容器中laradock用戶的.bashrc
然後需重新build workspace容器
# docker-compose build workspace

Dockerfile

以安裝 php:5.6-apache 為例
https://hub.docker.com/_/php

新建 Dockerfile 

內容為
FROM php:5.6-apache
COPY src/ /var/www/html/
新增目錄src 和 文件src/index.php

build Docker image

# docker build -t my-php-app .
Step 1/2 : FROM php:5.6-apache
5.6-apache: Pulling from library/php
...
他會從線上把 php:5.6-apache 拉下來,用下面方法查看
# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
my-php-app              latest              10cc9a5aa0c2        25 seconds ago      355MB
...
php                     5.6-apache          24c791995c1e        14 months ago       355MB

刪除dangling的images(部份<none>TAG的image)

https://stackoverflow.com/a/33913711
因為每次都build同一個image名字時,前一個同名的image的REPOSITORY和TAG會變成<none>
# docker rmi $(docker images --filter "dangling=true" -q --no-trunc)


啟動容器

# docker run -d --name my-running-app -p 5656:80 -v /root/php5.6-apache/src:/var/www/html my-php-app:latest

--name my-running-app => 指定容器的名字
-p 5656:80 => 容器中的80端口對應到host的5656端口,http://192.168.1.9:5656/ 可訪問容器中的web伺服器
-v /root/php5.6-apache/src:/var/www/html => host的/root/php5.6-apache/src對應到容器中的/var/www/html,直接改host目錄的文件容器中文件就會改動

進入容器

# docker exec -it my-running-app bash
用 -d 啟動後再用此目錄進容器,否則容器內的apache不會啟動

停止容器

# docker stop my-running-app

刪除 Exited 的容器

# docker rm my-running-app

進階使用

Dockerfile
FROM php:5.6-apache
COPY src/ /var/www/html/
RUN docker-php-ext-install mysqli \
    && apt-get update \
    && apt-get install -y libfreetype6-dev libjpeg62-turbo-dev \
    && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
    && docker-php-ext-install gd \
    && pecl install xdebug-2.5.5 && docker-php-ext-enable xdebug \
    && echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" >> /usr/local/etc/php/php.ini  \
    && echo "xdebug.remote_enable=1" >> /usr/local/etc/php/php.ini \
    && echo "xdebug.remote_connect_back=1" >> /usr/local/etc/php/php.ini \
    && echo "xdebug.idekey=PHPSTORM" >> /usr/local/etc/php/php.ini \
    && echo "xdebug.remote_log=/tmp/xdebug.log" >> /usr/local/etc/php/php.ini

註:
安裝mysqli
安裝gd函式庫
安裝xdebug並配置


使用docker安裝beanstalk console

github上推薦用composer安裝,但是如果你的機器沒有php和composer,你可以這樣做。直接拉取github上專案
$ git clone https://github.com/ptrofimov/beanstalk_console.git
$ cd beanstalk_console/
$ docker build --rm -t beanstalk_console .
$ docker run -d -p "8899:80" --name beanstalk_console beanstalk_console

然後瀏覽器打開 http://x.x.x.x:8899  即可顯示 Beanstalk console

在容器內測端口

https://stackoverflow.com/a/2226759  Test if port open and forwarded using PHP
php-fpm容器內可能沒有telnet,可以用PHP去測端口通不通
$host = 'stackoverflow.com';
$ports = array(21, 25, 80, 81, 110, 443, 3306);

foreach ($ports as $port)
{
    $connection = @fsockopen($host, $port);

    if (is_resource($connection))
    {
        echo '<h2>' . $host . ':' . $port . ' ' . '(' . getservbyport($port, 'tcp') . ') is open.</h2>' . "\n";

        fclose($connection);
    }

    else
    {
        echo '<h2>' . $host . ':' . $port . ' is not responding.</h2>' . "\n";
    }
}
輸出:
stackoverflow.com:21 is not responding.
stackoverflow.com:25 is not responding.
stackoverflow.com:80 (http) is open.
stackoverflow.com:81 is not responding.
stackoverflow.com:110 is not responding.
stackoverflow.com:443 is not responding.
stackoverflow.com:3306 is not responding.

如果端口忽然不通可以嘗試重啟docker

參考資料:

https://blog.gtwang.org/linux/centos-linux-7-install-docker-tutorial/  CentOS Linux 7 安裝 Docker 步驟與使用教學
https://github.com/NaturalHistoryMuseum/scratchpads2/wiki/Install-Docker-and-Docker-Compose-(Centos-7)   Install Docker and Docker Compose (Centos 7)