---
# System prepended metadata

title: Bash、網路、Docker

---

# Bash、網路、Docker
## Bash
### 什麼是Bash？
```bash
# 查看 current process (靜態截圖)
$ ps
# 查看 process (動態)
$ top
```
current process會佔CPU
.
```bash
# 查看 bash 應用程式的位置
$ which bash
```
install 的原理很簡單
.

```bash
# 查看 bash 的使用手冊
$ man bash
$ bash --help
```
[where an application parses options and string](https://github.com/bminor/bash/blob/f3b6bd19457e260b65d11f2712ec3da56cef463f/shell.c#L313)

### 其他好用的指令

## 網路基礎概念
### 網路怎麼組成的？
```bash
# 查看網路卡詳細資訊
$ sudo lshw -class network

# 查看主機的網路介面
$ ip link show
```

```bash
# 查看路由和Gateway
$ route -n
```

### 真正的封包格式長怎樣？
```bash
# 查看 mac 和 ip 位址
$ ip a show
```
[乙太header](https://elixir.bootlin.com/linux/v6.10.3/source/include/uapi/linux/if_ether.h#L173)
[ipv4 header](https://elixir.bootlin.com/linux/v6.10.3/source/include/uapi/linux/ip.h#L87)
[ipv6 header](https://elixir.bootlin.com/linux/v6.10.3/source/include/uapi/linux/ipv6.h#L118)

### 傳輸層
```bash
# 查看開啟的 port
$ netstat -tulpn | grep LISTEN

# 沒有該指令先安裝工具，再執行上面的
$ sudo apt install net-tools
```
### 為主機安裝ssh服務
```bash
# 先檢查ssh狀態，亮綠燈代表服務正常，沒服務要安裝
$ sudo systemctl status ssh

# 安裝 ssh 服務
$ sudo apt-get install openssh-server
# 啟動服務
$ sudo systemctl enable ssh --now
# 再次檢查狀態
$ sudo systemctl status ssh
```
用其他主機 ssh 該主機
```bash
$ ssh 使用者名稱@ip位址
```
若無法 ssh，可能是本身就聯繫不上主機
VM 可把網路卡改成橋接(給他真實的ip)
```
$ ping 提供ssh服務的ip位址
```
## Docker
### 在 Mac 安裝
要求：2010年後的 Mac 都可以
https://docs.docker.com/desktop/install/mac-install/
### 在 Linux 安裝 ─ 以 Ubuntu 為例
https://docs.docker.com/engine/install/ubuntu/
```bash
# 確認系統是否支援，我的 noble 有列在官網支援的 LTS
$ lsb_release -cs
cat /etc/lsb-release

# 系統更新
$ sudo apt update -y
sudo apt upgrade -y
sudo apt autoremove -y

# 設定 Docker repo
# Add Docker's official GPG key:
$ sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings # 建立(安裝)目錄
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc # a (all: u, g, and o)，所有群組 + read 權限

# Add the repository to Apt sources:
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

# 安裝 Docker 套件
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```

檢查安裝狀況
```bash
# 查看 docker 版本
docker --version
```
### Docker 包裝容器主流程
1. 建立 repository (專案資料夾)
    ```bash
    mkdir myapp
    cd myapp
    ```
2. 編寫應用程式: 以 node.js 為例
    ```bash
    # 確認 node 有無安裝
    node -v
    # 沒安裝也沒關係，到時候docker裡面有，所以本地不用安裝node
    vim hello.js
    
    console.log("Hello world.")
    
    ```
    ![image](https://hackmd.io/_uploads/rJJrG23FR.png)
    src: https://gitbook.tw/chapters/command-line/vim-introduction
4. 撰寫 Dockerfile 打包腳本
    node 的版本號可以去 DockerHub查詢
    ```bash
    $ vim Dockerfile
    
    FROM node:版本號

    RUN mkdir /src

    COPY hello.js /src

    CMD ["node","/src/hello.js"]
    
    ```
5. 用 Docker Engine 打包應用成 image
    ```bash
    # "."代表以當前目錄為根目錄，進行建立
    sudo docker image build -t userName/imageName:versionTag .
    sudo docker image ls
    # 在本地環境執行應用程序
    sudo docker container run userName/imageName:versionTag
    # 查看背景執行的應用
    sudo docker ps -l
    ```
6. 把 image 推送到 DockerHub
    ```bash
    docker login
    # 輸入 DockerHub 的帳密
    docker push userName/repoName:tagName
    ```
7. 別台電腦從 DockerHub 把 image 拉下來執行
    ```bash
    sudo docker image pull userName/repoName:tagName
    sudo docker container run userName/repoName:tagName
    ```

### Docker 部署服務: nginx web server
先去 nginx 官網看 LTS 版本號

[nginx: download](https://nginx.org/en/download.html)

到DockerHub搜尋nginx，alpine核心最小

```docker
nginx > Tags > 找 LTS 版本號
```
拉 image
```bash!
sudo docker pull nginx:1.25-alpine
sudo docker image ls
```
執行容器，查看該容器的系統檔案內容
```bash
# 列出容器內目錄
sudo docker run nginx:1.25-alpine ls
# 列出容器和新版本
sudo docker run nginx:1.25-alpine cat /etc/os-release
# 列出nginx設置目錄
sudo docker run nginx:1.25-alpine ls -R -l /etc/nginx
# 查看nginx全局設置文件
sudo docker run nginx:1.25-alpine cat /etc/nginx/nginx.conf
# 查看默認Web虛擬機設置文件
sudo docker run nginx:1.25-alpine cat /etc/nginx/conf.d/default.conf
# 確認虛擬目錄下面的內容
sudo docker run nginx:1.25-alpine ls -R -l /usr/share/nginx/html
```
(題外話，關於 ENTRYPOINT)
```bash
# docker run syntax
docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]
```
指令如果沒有加上 `[COMMAND]` `[ARG...]`，則`[COMMAND]`執行dockerfile設定的`ENTRYPOINT`，`CMD`的內容做為`[ARG...]`

進入容器，與容器互動
```bash
sudo docker run -it nginx:1.25-alpine /bin/sh
# 離開容器
Ctrl + P
Ctrl + Q
```


啟動服務到 port
```bash
 # 啟動虛擬機確認效果，容器內是80，本機用8080映射到容器的80
sudo docker container run --name myweb -d -p 8080:80 nginx:1.26
sudo docker container ls
# 服務狀態確認，要用本機的8080
# 它台電腦訪問要用 網卡ipv4:8080
curl http://127.0.0.1:8080
# 停止容器服務
sudo docker container stop myweb
# 啟動已存在的容器服務
sudo docker container start myweb
```

刪除容器
```bash
# 查看所有存在的容器(無論有無運作)
$ sudo docker ps -a
# 刪除容器
$ docker container rm [CONTAINER_ID 或 NAMES] 
# 正在執行的容器山不掉，要先停止再刪
$ sudo docker container stop [CONTAINER_ID 或 NAMES] 
docker container rm [CONTAINER_ID 或 NAMES] 
# 或是強制刪除
docker container rm -f [CONTAINER_ID 或 NAMES] 
```
刪除映像檔
```bash
# 查看本機擁有的映象
sudo docker image ls
# 刪除映像
sudo docker rmi REPOSITORY:TAG
```
(快捷)移除所有容器
```bash
# 停止執行所有容器
sudo docker stop $(docker ps -a -q)
# 刪除所有容器
sudo docker container prune
sudo docker rm $(docker ps -a -q)
```
### Docker Volume: PostgreSql
```bash
# 安裝
sudo docker pull postgres:16.2-alpine3.19
# 啟動webdb，設定超級用戶的帳密
sudo docker run --name webdb -p 5432:5432 -e POSTGRES_USER=dbuser -e POSTGRES_PASSWORD=12345678 -d postgres:16.2-alpine3.19
# 用nmap查看資料庫服務
nmap 127.0.0.1
```
存取 webdb
```bash
# 用 psql 連接 webdb，debian分支的OS要加特定版本號，所以不能用postgresql-client-common
sudo apt install postgresql-client
psql -h localhost -U dbuser
Password for user dbuser:
dbuser= # 輸入密碼
dbuser=# select * from pg_tables;
dbuser=# \q
```
建立專用的Volume
```bash
# 如果沒有指定volume就直接執行db會自動生成一個名字很難記的volume
sudo docker volume ls
# 先把舊的 webdb 清掉
docker stop webdb
docker rm webdb
```
```bash
# 建立有名字的 volume
sudo docker volume create --name v_webdb_data
# 可用 docker volume rm volumeName 刪除不要的volume
sudo docker volume ls
sudo docker volume inspect v_webdb_data
# Mountpoint: 在本機目錄建立volumes
```
建立新的webdb
```bash
# 多了綁定volume和postgres主目錄的動作
sudo docker run --name webdb -v v_web_data:/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=dbuser -e POSTGRES_PASSWORD=12345678 -d postgres:16.2-alpine3.19
# 查看webdb描述
sudo docker inspect webdb
```