---
# System prepended metadata

title: '**Docker**'

---

# **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&noteKey=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
![](https://i.imgur.com/zCqWb1p.png)

內容
```
#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&noteKey=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**
![](https://i.imgur.com/0UWBGuU.png)
```
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)


![](https://i.imgur.com/l5TTy2o.png)

點擊Test Connection

![](https://i.imgur.com/AEYcPzz.png)

完成

**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