# Docker Note ###### tags: `docker` [Docker ARG, ENV 有什麼不同](https://blog.scottchayaa.com/post/2018/11/04/docker-arg-env-variable/) Docker Compose: 用 yml 定義多個容器連結方式的解決方案 ---- [30 天與鯨魚先生做好朋友](https://ithelp.ithome.com.tw/users/20102562/ironman/3746) Terms in Docker: - image - container - host - repository 背景執行 container `-d` ``` docker run -d httpd ``` ## Prot forwarding container 具有隔離特性,也就是每個 container 都是獨立的個體,它們各自有屬於自己的 80 port 可以用,因此才不會相衝。 今天的目標是要從外界存取 container,因此要做點手腳才行--正是標題提到的 port forwarding。Docker 使用 -p 選項設定 port forwarding,範例如下: ```bash= # 加上 -p 參數 docker run -d -p 8080:80 httpd # 確認 port 有被開出來了 curl http://localhost:8080/ ``` ## Volume Volume 也是 Docker 的元件,它提供 container 保存資料或共享資料的機制。 開啟 container 後,可以進到 container 裡去做操作。例如進到 httpd container 中去修改靜態網頁內容。 但這個做法,每次開新的容器後又會刷新,所以可以綁定 host 和 container 的路徑,讓容器可以存取。 Bind Mount ```bash= # 執行 container docker run -d -it -v `pwd`:/usr/local/apache2/htdocs -p 8080:80 httpd # 測試對應路徑 curl http://localhost:8080/test.html ``` ## Network Network 也是 Docker 的元件 有了 Docker 後,開 server 變得容易許多。但實務上的網路架構,通常是多層式的,如三層式架構(Three-Tier)需要 Application Server 與 RDBMS 兩種 server 連結起來,才能提供完整的服務。 ### 觀察背景執行的容器 ``` # Terminal 1 docker run -d -it --name web -p 8080:80 httpd # 加 -f 選項後,container log 只要有更新,畫面就會更新 docker logs -f web # Terminal 2 curl http://localhost:8080/ ``` ### Connect containers ```bash= # wget 為 curl 的替代指令 docker run --rm busybox wget -q -O - http://web/ # 比較沒加 link 與有加 link 的差別 docker run --rm --link web busybox wget -q -O - http://web/ # 使用別名 docker run --rm --link web:alias busybox wget -q -O - http://alias/ ``` 執行 BusyBox 的 wget -q -O - http://web/ 的 web 對應的是 Apache container 的 --name web 設定。另外,必須要使用 container 內部的 port(本例是 80)呼叫。 --link 選項的用法:web:alias 左邊是 container name,右邊是別名。設定完後,web 和 alias 都能通。 ### Use network ```bash= # 建立 network docker network create my-net # Terminal 1 啟動 Apache docker run --rm --name web -p 8080:80 --network my-net httpd # Terminal 2 透過 BusyBox 連結 Apache docker run --rm --network my-net busybox wget -q -O - web ``` `-O` output file. If no given, no file will be saved `-q` quit. If this on, no download status will display ### -\-link 的問題 >The Linked can't interact with the linker. ### Summary - `link` only has one direction - `network` a container can connect to each others in a same Network ![](https://i.imgur.com/PyPQ5KK.png) ## Enviroment ```bash= # 查看原本的 env docker run --rm busybox env # 給 env 設定後再看 env 的內容 docker run --rm -e DB_HOST=mysql busybox env ``` ### Build a phpmyadmin connected to DB ```bash= # Terminal 1,使用 MYSQL_ROOT_PASSWORD 與 MYSQL_DATABASE docker run --rm -it --name db -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=demo mysql/mysql-server # Terminal 2 docker run --rm -it --link db -p 8080:80 phpmyadmin ``` > Host XXX is not allowed to connect to this MySQL server -> https://github.com/docker-library/mysql/issues/275 Check user and host ```sql= SELECT host, user FROM mysql.user; ``` So let's add a new user CREATE USER 'user'@'%' IDENTIFIED BY 'password'; The first thing to do is to provide the user with necessary permission and here I have given all permission to the particular user. ```sql= GRANT ALL PRIVILEGES ON * . * TO 'user'@'%'; Reload all the privileges. ``` Remeber to flush privileges after alter privileges ```sql= FLUSH PRIVILEGES; ``` If you want to allow range of IPs to a particular user use as follows 10.1.1.% ```sql= GRANT ALL PRIVILEGES ON * . * TO 'user'@'10.1.1.%'; ```` > Note: Here host Name = % and that means you can access this database server from any host. Granting all privileges to the user is a big risk and that's not a best practice. Further you can replace user 'user' to 'bob'. docker-compose reference for mysql: https://github.com/docker-library/mysql/issues/275 ## 應用 - 遠端資料庫版本多樣,本端不用安裝對應版本,而是用容器連線 - 測試同一份 source code 在不同版本語言下測試 - 不用安裝一些非常用軟體、語言但還是可以用 ### 進階懶人 [alias](https://linuxhint.com/configure-use-aliases-zsh/) ```shell= # 使用 Composer alias composer="docker run -it --rm -v \$PWD:/source -w /source composer:1.10" # 使用 npm alias npm="docker run -it --rm -v \$PWD:/source -w /source node:14-alpine npm" # 使用 Gradle alias gradle="docker run -it --rm -v \$PWD:/source -w /source gradle:6.6 gradle" # 使用 Maven alias mvn="docker run -it --rm -v \$PWD:/source -w /source maven:3.6-alpine mvn" # 使用 pip alias pip="docker run -it --rm -v \$PWD:/source -w /source python:3.8-alpine pip" # 使用 Go alias go="docker run -it --rm -v \$PWD:/source -w /source golang:1.15-alpine go" # 使用 Mix alias mix="docker run -it --rm -v \$PWD:/source -w /source elixir:1.10-alpine mix" ``` - docker run -w ``` -w|--workdir 指定預設執行的路徑 ``` # Docker Compose Build and run mutiple containers at once First, we need to learn how to write `docker-compose.yml`, which is a config file that records all setup we desire Build a database and make phpmyadmin server connect to the database. ```yml # docker-compose version version: "3.8" networks: net: services: db: image: mariadb:10.3 environment: MYSQL_ROOT_PASSWORD: pass networks: net: phpmyadmin: image: phpmyadmin environment: PMA_HOST: db ports: - 8080:80 networks: net: ``` create containers and run ``` docker-compose up ``` also delete exited containers ``` docker-compose up --remove-orphans ``` ### mysql database 的雷 不同 db 映像檔預設的使用者和權限不一樣,如果要不限 IP 的話,host 要為 % (means any) - mysql/mysql-server: need to alter - mariadb: ready to go as build ![](https://i.imgur.com/NEiAuze.png) 可以透過 [Privilege 相關的 query](#Build-a-phpmyadmin-connected-to-DB) 調整,也可以直接 update 資料庫 ```sql UPDATE mysql.user SET host = '%' WHERE user = 'root' AND host = 'localhost'; ``` 調完記得 flush ```sql= FLUSH PRIVILEGES; ``` 更多權限調整:https://phoenixnap.com/kb/how-to-create-new-mysql-user-account-grant-privileges ## Docker commit 最開始,得先了解 Docker image 的基本概念。首先最基本的,Docker 是採用 Union 檔案系統(簡稱 UnionFS)來儲存 image。 - 分層式的檔案系統 - 支援把「檔案系統的修改」作為 commit,讓多個 commit 一層層堆疊 - 支援把多個目錄掛載到同一個虛擬檔案系統下 summary - 可以克制化 ---- 信號 http://shihyu.github.io/books/ch33s01.html