# **Docker**
**安裝Docker流程**
**docker desktop 安裝(Windows)**
**1.安裝網址:https://docs.docker.com/desktop/install/windows-install/**
**2.驗證docker版本、進行測試安裝是否成功**
```
PowerShell
docker --version
docker images
docker pull hello-world
docker images
docker run hello-world
```
**P.S.參考文件**
https://www.evernote.com/shard/s475/client/snv?noteGuid=ca24e8d3-7774-1d2c-a4b7-aea354aee165¬eKey=9df30b0a5cedce798f394386637797eb&sn=https%3A%2F%2Fwww.evernote.com%2Fshard%2Fs475%2Fsh%2Fca24e8d3-7774-1d2c-a4b7-aea354aee165%2F9df30b0a5cedce798f394386637797eb&title=%25E7%25AC%25AC%2B2%2B%25E7%25AB%25A0%2BDocker%2B%25E5%25A6%2582%25E4%25BD%2595%25E5%259C%25A8%25E4%25B8%258D%25E5%2590%258C%25E4%25BD%259C%25E6%25A5%25AD%25E7%25B3%25BB%25E7%25B5%25B1%25E4%25B8%258A%25E4%25BD%25BF%25E7%2594%25A8
---
# **Java建置&tar匯出&資料庫匯出**
**1.專案下建立設定檔**
Dockerfile

內容
```
#Dockerfile
FROM openjdk:8-jdk-alpine
COPY ./target/*.jar /Documents/mydocker/demo.jar
WORKDIR /Documents/mydocker
RUN sh -c 'touch demo.jar'
ENTRYPOINT ["java","-jar","demo.jar"]
```
[Dockerfile](https://matthung0807.blogspot.com/2020/11/docker-what-is-dockerfile.html)指令簡單說明
1. `[FROM](https://docs.docker.com/engine/reference/builder/#from) openjdk:8-jdk-alpine`:使用的base image。
2. `[COPY](https://docs.docker.com/engine/reference/builder/#copy) ./target/*.jar /Documents/mydocker/demo.jar`:將build context,即所在目錄的`target/*.jar`複製到container檔案目錄的/Documents/mydocker/demo.jar。
3. `[WORKDIR](https://docs.docker.com/engine/reference/builder/#workdir) /Documents/mydocker`:指定container的`/Documents/mydocker`為Docker的命令執行目錄。
4. `[RUN](https://docs.docker.com/engine/reference/builder/#run) sh -c '[touch](http://linux.vbird.org/linux_basic/0220filemanager.php#touch) demo.jar'`:修改`demo.jar`的時間戳記為目前時間。
5. `[ENTRYPOINT](https://docs.docker.com/engine/reference/builder/#entrypoint) ["java","-jar","demo.jar"]`:在container剛指定的`WORKDIR`目錄執行`java -jar demo.jar`。
**2.建立專案jar包**
執行Run As 中的 Maven clean & Maven install
---> 開始打包
生成路徑
linux:
/home/'user名稱'/'專案讀取路徑'/target/'專案.jar'
windows:
C:\\'專案路徑下'\\'專案讀取路徑'\\target\\'專案.jar'
**3.切換到檔案路徑**
cd '準備執行的jar檔的路徑'
wsl下的linux參考路徑
```
cd \\wsl.localhost\Ubuntu-20.04\home\tkbuser\Desktop\Workspace\Training_test
```
```
cd \\wsl$\Ubuntu\home\tkb0004757\Desktop\TkbGitProject\forecast
```
**4.打包專案並於Docker執行**
```
docker build -t '專案名稱'-app .
```
**5.由Windows連線到Container**
docker run -p 8080:8050 forecast-app
前面的port號為windows的
後面的port號為Container的(要跟原來專案一樣)
最後打上image名稱
```
cd C:\Users\TKB0004757
```
```
docker run -p 8080:8050 forecast-app
```
**6.開啟瀏覽器**
```
localhost:8080/'專案'/
```
**7.打包為tar壓縮檔**
```
docker save forecast-app -o forecast-app.tar
```
**8.tar就會生成在當前的路徑下**
**9.資料庫匯出**
```
[mysqldump -u tkb0004558 -p project > member20220802.sql]
mysqldump -u 使用者名稱 -p 資料庫名 表名> 匯出的檔名
```
**10.完成**
**P.S.參考文件**
https://www.evernote.com/shard/s475/client/snv?noteGuid=cd7703dd-8897-a1ca-6b24-4e4cefaa2b4e¬eKey=3c123e129886329f917f140bcc125f7f&sn=https%3A%2F%2Fwww.evernote.com%2Fshard%2Fs475%2Fsh%2Fcd7703dd-8897-a1ca-6b24-4e4cefaa2b4e%2F3c123e129886329f917f140bcc125f7f&title=%25E5%258C%25AF%25E5%2587%25BADocker%25E6%25AA%2594%25E6%25A1%2588
---
# **建議方式**
**安裝**
從官方存儲庫安裝 Docker
**第1步:更新軟件存儲庫**
首先打開一個終端窗口並更新本地存儲庫:
```
sudo apt update
```
等待該過程完成。
**第2步:下載依賴項**
通過運行以下命令,允許您的 Ubuntu 20.04 系統通過 HTTPS 訪問 Docker 存儲庫:
```
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
```
上面提到的命令:
授予包管理器通過https傳輸文件和數據的權限。
允許系統檢查安全證書。
安裝curl,一個用於傳輸數據的工具。
添加用於管理軟件的腳本。
**第3步:添加 Docker 的 GPG 密鑰**
接下來,添加GPG密鑰以確保軟件包的真實性:
```
curl -fsSL [https://download.docker.com/linux/ubuntu/gpg](https://download.docker.com/linux/ubuntu/gpg) | sudo apt-key add -
```
**第4步:安裝 Docker 存儲庫**
現在使用以下命令安裝 Docker 存儲庫:
```
sudo add-apt-repository "deb [arch=amd64] [https://download.docker.com/linux/ubuntu](https://download.docker.com/linux/ubuntu) $(lsb_release -cs) stable"
```
該命令為您的特定 Ubuntu 版本(在本例中為 20.04 Focal Fossa)安裝最新的存儲庫。
**第5步:安裝最新的 Docker**
首先再次更新存儲庫:
```
sudo apt update
```
現在您可以使用以下命令安裝最新的 Docker 版本:
```
sudo apt-get install docker-ce
```
**第6步:驗證 Docker 安裝**
要確認安裝,請檢查 Docker 的版本:
```
docker --version
```
它應該顯示 Docker 版本。
**第7步:[啟動Docker]**
```
sudo service docker start
```
**第8步:[測試docker engine可否使用 先看images檔案]**
```
sudo docker images
```
**第9步:[空的,現在建立images檔案上去]**
```
sudo docker pull hello-world
```
**第10步:[再看一次images就會有data]**
```
sudo docker images
```
**第11步:[run hello-world]**
```
sudo docker run hello-world
```
**第12步:[關閉docker服務]**
```
sudo service docker stop
```
---
# **Mysql、Springboot建立連線 (第一種方法)**
**MySQL**
docker安裝mysql
```
docker pull mysql:8
```
**確認是否安裝完成**
```
docker images
```
**建立網路**
```
docker network create 'image名稱'
```
**docker network ls 查看是否建立成功**
```
docker network ls
```
**建立Container並執行**
```
docker run --name mysqldb --network 'image名稱' -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=docker -e MYSQL_USER=root -e MYSQL_PASSWORD=123456 -d mysql:8
```
**查查看Container是否建立**
```
docker ps
```
**測試連線帳號**
```
docker exec -it container ID bash
mysql -u帳號 -p密碼
```
**指令整理**
```
查看 images
docker images
移除 images
docker rmi ' xxxxxxxxxx '
查看 network
docker network ls
啟動 docker
docker-compose up
查看 container中的東西
docker ps -a
```
---
# **SpringBoot**
**設定**
根據上面自己建立image的設定,建立application.properties檔案
```
spring.datasource.url=jdbc:mysql://mysqldb:3306/docker
spring.datasource.username=username
spring.datasource.password=123456
spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
```
**1.將專案打包成jar檔**
**2.Dockerfile配置**
```
FROM openjdk:8
EXPOSE 8080
ADD target/spring-boot-docker.jar test1.jar
ENTRYPOINT ["java","-jar","/test1.jar"]
spring-boot-docker.jar是專案打更成jar檔的黨名
test1.jar是打包到docker重新命名的名稱
ENTRYPOINT是把参数拼成一条命令java -jar test1.jar)
```
**建立image檔案 cd到自己的專案打指令**
```
sudo docker build -t springbootmysql .
```
**查看image**
username@DESKTOP-4SUA6UQ:~/Desktop/work/Login$ sudo docker images
**sudo**看目前使用的權限,再決定要不要加
```
sudo docker images
```
**建立跟mysql的連線**
```
sudo docker ps
```
**查看帳號**
```
SELECT User,Host FROM mysql.user;
```
**查帳號權限**
```
SHOW GRANTS FOR usernamer;
```
# **Docker Compose建立連線(第二種方法)**
**到專案新增yaml檔 (docker-compose.yml)**
docker-compose.yml
```
version: '3'
services:
loginserver:
build: .
ports:
- 8080:8080
networks:
- loginbridge
environment:
- spring.datasource.url=jdbc:mysql://mysqldbcompose:3306/dockerr
- spring.datasource.username=usernames
- spring.datasource.password=123456
- spring.datasource.driver-class-name =com.mysql.cj.jdbc.Driver
depends_on:
- mysqldbcompose
mysqldbcompose:
image: mysql:8
ports:
- '3307:3306'
environment:
MYSQL_DATABASE: 'dockerr'
MYSQL_USER: 'usernames'
MYSQL_PASSWORD: '123456'
MYSQL_ROOT_PASSWORD: '123456'
volumes:
- /app/mysql/db:/var/lib/mysql
- /app/mysql/conf/my.cnf:/etc/my.conf
- /app/mysql/init:/docker-entrypoint-initdb.d
networks:
- loginbridge
networks:
loginbridge:
# external: true 如果你的network是現有的 要加這句,docker引擎會先去找聲明過的不然會報錯
#MYSQL_USER:username、MYSQL_PASSWORD: password要跟properties的對到
```
cd進入到該專案
```
sudo docker-compose config -q
#查看yml格式對不對
```
啟動docker
```
sudo docker-compose up
```
**Dockerfile(3步驟)**
基本規定
```
- 保留字都須使用大寫,後面至少要跟一個參數
- 指令上到下執行
- 表示注釋
- 每條指令都會創建新的鏡像層並提交
```
建置流程
```
- docker從基礎image運行一個容器
- 執行一條Dockerfile指令對容器做修改
- 執行類似docker commit的操作提交一個新的image層
- docker再基於剛提交的image層運行一個新容器
- 再執行Dockerfile的下一條指令,直到指令都執行完成
```
編寫docker文件
```
FROM 基礎IMAGE,此鏡像作為模板建新鏡像
MAINTAINER 鏡像作者訊息
RUN 構建IMAGE執行的命令,每RUN一次都會構建一層IMAGE
VOLUME 定義數據卷,用於數據保存和持久化
USER 指定鏡像以哪種身分去執行,默認是root
WORKDIR 指定創建容器後,終端默認進來的工作目錄,一個落腳點
ARG 變量屬性值,但不在容器內部起作用
EXPOSE 暴露端口
ENV 構建IMAGE時,設定環境變量,可以在後續的任何Run指令使用,假如這裡設定變量路徑,
可以在WORKDIR指定這個變量路徑
ADD 將本機目錄下的文件複製到IMAGE且會自動處理URL和解壓TAR包
(假如要在IMAGE安裝JDK8,就可以複製本機的JDK8.tar進去)
COPY 拷貝文件和目錄到IMAGE中
COPY src dest
COPY ["src","dest"]
<src原路徑>:原文件或目錄
<dest目標路徑>:容器內的指定路徑,會自動建立
CMD 容器啟動後的命令,如果有多個則以最後一個為準,也可以為ENTRYPOINT提供參數
ENTRYPOINT 容器進入時執行的命令
ENTRYPOINT 和 CMD 使用可看下圖
```
實際使用
```
FROM openjdk:8
EXPOSE 8080
ADD target/spring-boot-docker.jar test1.jar
ENTRYPOINT ["java","-jar","/test1.jar"]
spring-boot-docker.jar是專案打更成jar檔的檔名
test1.jar是打包到docker重新命名的名稱
ENTRYPOINT是把参数拼成一条命令java -jar test1.jar)
```
docker build構建image
docker run image運行container
# **Docker-Compose**
**定義**
Docker公司推出的工具軟體,只需要定義一個YAML格式的配置文件,寫好多個容器間的調用關係,一個指令就能啟動、關閉。
**安裝Docker Compose**
在下載Compose (v2.6.1)
```
sudo curl -L "https://github.com/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
使用curl將Compose文件下載到/usr/local/bin目錄中。
```
增加寫的權限
```
sudo chmod +x /usr/local/bin/docker-compose
下載完成後,使用chmod修改docker-compose文件可執行權限。
```
驗證安裝是否成功
```
docker-compose --version
輸出將包含docker-compose版本信息docker-compose version v2.6.1。
```
Docker指令
Image
查看鏡像列表
```
docker images
```
刪除指定 id 的鏡像
```
docker rmi image-id
```
創建新的image
docker commit -m="描述訊息" -a="作者名" 當前容器id 鏡像名:版本號
docker commit -m="solve bash-4.4" -a="lai" 5d9d5cc6e877 lai/mysql:8
Network
```
作用
- 容器間互連、端口映射
- 容器ip變動時可以透過network_Name直接網路通信而不受影響
```
docker跟本機交流、容器和容器間的交流
```
docker啟動後,打ifconfig指令會發現多一個docker0的虛擬網橋
username@DESKTOP-4SUA6UQ:~$ ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
inet6 fe80::42:c3ff:fe3c:7962 prefixlen 64 scopeid 0x20<link>
ether 02:42:c3:3c:79:62 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 19 bytes 1706 (1.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
docker透過docker0和本機做交流、容器間交流
```
列出網路
```
root@DESKTOP-4SUA6UQ:/home/username# docker network ls
NETWORK ID NAME DRIVER SCOPE
fe410a2099d8 bridge bridge local
27ec28bbe5be host host local
9801a0aa540c none null local
預設會有3種模式bridge、host、none
bridge:為每個容器分配、設置IP...,並將容器連接到docker0,虛擬網橋 --(默認模式)
host :容器不會虛擬出自己的網卡、配置IP等,都是使用本機的IP、端口
none :容器有獨立的Network namespace,但並沒有任何網路設定 --(幾乎不用)
container:新建的容器沒有自己的網卡和自己的IP,而是和指定容器共享IP、端口範圍等
```
bridge模式
```
使用network bridge指定,不寫就 默認用docker0
```
host模式
```
使用network host指定
```
none模式
```
使用network none指定
```
container模式
```
使用network container:NAME或是容器ID指定
```
創建網路
```
docker network create xx_network
```
查看網路
```
docker network inspect xx_network
```
移除網路
```
docker network rm xx_network
```
將image專案run在container中(-d為不跑console)(--name為取的名字)(forecast-app是跑的image)
```
docker run -p 8080:8050 -d --name forecast-app1 forecast-app
```
# **Container**
**查看當前運行中的容器**
```
docker ps
```
**查看所有容器**
```
docker ps -a
```
**刪除指定 id 的容器**
```
docker rm container-id
```
掛載資料
docker run -it --privileged=true -v /**本機絕對路徑**:/**容器內目錄:ro** **容器名**
將本機儲存位置掛載到容器內目錄,當容器刪除時,資料還會保留在本機
```
docker run -it --privileged=true -v /app/mysql/db:/var/lib/mysql login-mysqldbcompose-1
:ro是設定唯讀,預設是rw 如果沒有要特別設定的話就不用打這個
```
**掃描容器的配置 **
```
docker inspect 容器id
```
"Mounts": 掛載位置
```
"Mounts": [
{
"Type": "bind", //綁定類型
"Source": "/app/mysql/db", //本機儲存的位置
"Destination": "/var/lib/mysql", //container內儲存的位置
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/app/mysql/conf/my.cnf",
"Destination": "/etc/my.conf",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
{
"Type": "bind",
"Source": "/app/mysql/init",
"Destination": "/docker-entrypoint-initdb.d",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
}
],
```
查看 volume 列表
```
docker volume ls
```
停止/啟動指定 id 的容器
```
docker stop/start container-id
```
---
# **Docker部屬**
**JAVA流程**
```
docker
#打包
docker save [image] -o file.tar
#上傳伺服器後執行
docker load -i file.tar
#DB
docker run -p 3306:3306 -v /etc/localtime:/etc/localtime:ro --name mariadb -e MYSQL_ROOT_PASSWORD=123456 -d docker.io/library/mariadb:10.3
#JAVA
docker run -d -v /etc/localtime:/etc/localtime:ro --link mariadb:mariadb --name teacherresource-20221210 -p 8080:8080 teacherresource-app
#Nuxt
docker run -d -v /etc/localtime:/etc/localtime:ro --link teacherresource-app:teacherresource-app --name nuxt-app:v1 -p 3000:3000 nuxt-app:v1
#查詢container IP
docker inspect --format '{{ .NetworkSettings.IPAddress }}' mariadb
CREATE SCHEMA `tkb_demo` DEFAULT CHARACTER SET utf8mb4;
#外面匯入SQL進container
cat teacher_resource.sql | docker exec -i mariadb mysql -u root --password=123456 teacher_resource
```
---
# **Docker-MySQL Workbench**
在Docker 使用MySQL container時,是沒有GUI操作介面的,用指令修改資料是比較耗時的,所以我們如何幫container中的MySQL建立一個Workbench來使用呢,作法就是把本機的port連到container內的port。
**第一步: run mysql/mysql-server:5.7 image**
docker run -p 3400:3306 --name my-mysql -e MYSQL_ROOT_PASSWORD=root -d mysql/mysql-server:5.7
**第二步: 進到MySQL container內**
```
docker exec -it my-mysql /bin/bash
```
**第三步: 登入MySQL**

```
docker exec -it my-mysql /bin/bash
```
```
mysql -uroot -p -A
```
**第四步: 查看所有使用者及host**
```
select user,host from mysql.user;
```
**第五步: 把root user的host改為 %**
指令: update mysql.user set host=’%’ where user=’root’
因為localhost表示你只能在container進行連線,外部連線不了
```
update mysql.user set host='%' where user='root';
```
**第六步: 更新特權**
```
flush privileges
```
**第七步: 在windows中打開workbench設定連線**
1. Connection 名稱
2. 主機連線到mysql container內的port號 (上面我設3400:3306),所以是3400
3. 設定密碼(建立mysql container時我設的密碼環境變數為root)

點擊Test Connection

完成
**P.S.參考文件**
https://flannel-october-6b3.notion.site/Docker-f73f5ac983394c73bc5b70b1dc191561
---
# **Docker Compose**
**建立dockerCompose.yml**
放入組態設定
```
yml(yaml)
version: '3.7'
# Service
services:
# Database MySQL
app-db:
image: mariadb
container_name: app-mariadb
#restart: always
volumes:
- mysql-data:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: 123456
MYSQL_DATABASE: mms_db
MYSQL_USER: springboot
MYSQL_PASSWORD: springboot
ports:
- "3306:3306"
networks:
- app-server-network
# APP Server
app-server:
depends_on:
- app-db
image: mms/member-manage-system:0.0.1
build:
context: ./
dockerfile: Dockerfile
ports:
- "8080:8080"
environment: # Pass environment variables to the service
DATASOURCE_HOST: app-db
DATASOURCE_POST: 3306
DATASOURCE_NAME: mms_db
DATASOURCE_USERNAME: springboot
DATASOURCE_PASSWORD: springboot
networks:
- app-server-network
# Volume
volumes:
mysql-data:
# Network
networks:
app-server-network:
```
```
docker
docker-compose -d up
```
---
# **nuxt dockerize 流程**
**1. 建立Nuxt專案**
```
PowerShell
npx create-nuxt-app 專案名稱
```
**2. 在nuxt.config.js設定好server host 及 port 及 axios 連線**
這裡設定正式環境host為0.0.0.0, port為3000
```
JavaScript
export default {
...
server: {
host: process.env.NODE_ENV === 'development' ? '127.0.0.1' : '0',
port: process.env.NODE_ENV === 'development' ? 8500 : 3000,
},
axios: {
baseURL:
process.env.NODE_ENV === 'development'
? 'http://127.0.0.1:4000/'
// 實際會連線到此網站的ip
: 'https://p22sg03.csofe.org/'
},
...
}
```
**3. 更新連線後端IP**
```
JavaScript
// /server/app.js
...
const API_URL =
process.env.NODE_ENV === 'development'
? 'http://172.18.48.25:8765/api'
// api server的container ip
: 'http://172.17.0.3:8080/api'
...
```
**4. 在根目錄新增Dockerfile**
```
yml(yaml)
FROM node:16-bullseye
WORKDIR /app
ENV NUXT_HOST=0.0.0.0
ENV NUXT_PORT=3000
COPY . /app
RUN npm cache clean --force
RUN npm install
RUN npm run build
EXPOSE 3000
CMD ["npm", "run", "start"]
```
**5. 在專案根目錄將專案 build 成 image**
```
PowerShell
docker build -t nuxt-app:v1 .
```
**6. 運行成container
```
PowerShell
// 依專案設定
```
**7. 成功! 可以用 https://p22sg03.csofe.org/ 來連線此專案 **
yaml 配置規劃
https://ithelp.ithome.com.tw/articles/10191753