# docker ## 下載安裝 >[Install Docker Engine on CentOS](https://docs.docker.com/engine/install/centos/#install-using-the-repository) >使用第一種方法 >流程: >1.Set up the repository >2.Install Docker Engine >3.Start Docker. >4.Verify that Docker Engine is installed correctly by running the `hello-world` image.[color=yellow] >p.s.裝倉庫(repository)時,除了預設的stable channel之外有另外兩種nightly and test channels可選擇enable or not :::info nightly channel->gives you latest builds of work in progress for the next major release. test channel->gives pre-releases that are ready for testing before general availability (GA). ::: ## 理論流程 參考網站:[Docker 基礎教學與介紹 101](https://cwhu.medium.com/docker-tutorial-101-c3808b899ac6) docker->以應用程式為核心虛擬化(取代傳統需要VM建置環境的虛擬化技術) >傳統VM[color=#b259ea] ![](https://i.imgur.com/WOFoU1a.png) >containter(以應用程式為中心)[color=#6f50c4] >![](https://i.imgur.com/YzxQC1j.png) ## docker核心 參考網站:[《Docker —— 從入門到實踐》正體中文版](https://philipzheng.gitbook.io/docker_practice/) docker分為三種東西 >映像檔images >容器container >倉庫repository <font size = 5>***映像檔(鏡像)***</font>就是一個唯讀的模板,用來產生容器實體,類似於用於烤蛋糕的模具,藉由寫好的dockerfile建立 <font size = 5>***容器***</font>就像是用蛋糕模具烤出來的蛋糕本體,容器是用映像檔建立出來的執行實例。它可以被啟動、開始、停止、刪除。每個容器都是相互隔離、保證安全的平台。 ->可以被看成是一個執行的應用程式加上簡易版的執行環境(包括 root 使用者權限、程式空間、使用者空間和網路空間等) >註:映像檔是唯讀的,容器在啟動的時候建立一層可寫層作為最上層 <font size = 5>***倉庫***</font>存放映像檔的地方,可利用`pull`及`push`上傳或下載所需的映像檔 ## docker命令 ### 啟動 ``` systemctl start docker ``` ### 映像檔(鏡像檔image) #### 取得映像檔 `docker pull` 從倉庫中取得 ``` docker pull [完整的倉庫伺服器位址(沒有即註冊服務器(dockerhub))] [需要的映像檔] ``` #### 列出 `docker images`顯示本機已有的映像檔。 ``` 1. -a(列出本地所有的鏡像(包含中間映像層)) 2. -q(只顯示鏡像ID) 3. --digests(顯示鏡像的摘要資訊) 4. --no-trunc(顯示完整的鏡像資訊) ``` * 有以下幾個項目 * 來自於哪個倉庫,比如 ubuntu * 映像檔的標記,比如 14.04 * 它的 ID 號(唯一) * 建立時間 * 映像檔大小 #### 建立 >幾種方法 >1.修改已有映像檔 >2.利用 Dockerfile 建立映像檔 >3.從本機匯入 上傳映像檔 `docker push`把自己建立的映像檔上傳到倉庫中來共享 參考:[上傳 Docker Image 到 Docker Hub ](https://ithelp.ithome.com.tw/articles/10192824) #### 儲存和載入 建立映像檔到本地檔案,可以使用 `docker save` 命令。 可以使用 `docker load`從建立的本地檔案中再匯入到本地映像檔庫 ``` docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE ubuntu 14.04 c4ff7513909d 5 weeks ago 225.4 MB ... docker save -o ubuntu_14.04.tar ubuntu:14.04 ``` ``` docker load < ubuntu_14.04.tar ``` #### 移除 `docker rmi [要刪除的映象檔]` ``` docker rmi -f +要刪除的鏡像(強制刪除鏡像) docker rmi -f +要刪除的鏡像1 +要刪除的鏡像1(強制刪除多個鏡像) docker rmi -f $(docker images -qa) 刪除全部容器 ``` #### 尋找 `docker search`會於docker hub上找尋映像檔 ``` docker search [option] 鏡像名字 ``` ### 容器 #### 啟動及更動 ``` docker run [OPTIONS] IMAGE[COMMAND][ARG…] ``` 當利用 `docker run` 來建立容器時,Docker 在後臺執行的標準操作包括: * 檢查本地是否存在指定的映像檔,不存在就從公有倉庫下載 * 利用映像檔建立並啟動一個容器 * 分配一個檔案系統,並在唯讀的映像檔層外面掛載一層可讀寫層 * 從宿主主機設定的網路橋界面中橋接一個虛擬埠到容器中去 * 從位址池中設定一個 ip 位址給容器 * 執行使用者指定的應用程式 * 執行完畢後容器被終止 >[OPTIONS] > -t:選項讓Docker分配一個虛擬終端(pseudo-tty)並綁定到容器的標準輸入上 > -i:則讓容器的標準輸入保持打開 > -it:創造互動式容器,可以透過所建立的終端來輸入命令 > –name: > ``` > docker run --name 想命名的容器 想命名的名字 > docker run --rename 想命名的容器 想命名的名字 > (可直接用docker rename 想命名的容器 想命名的名字) > ``` > -d:守護態(後台運行)(後臺開啟如果沒指定作業會自行關閉) > -P(以預設去分配窗口(接口)) > -p(指定窗口(接口)) > >有幾種模式: > >ip:hostPort:containerPort > >ip::containerPort > >hostPort:containerPort > >containerPort > >EX:`docker run -it -p 8080:8080 tomcat` > >[color=blue] #### 查看 ``` docker ps [OPTIONS] docker container ls docker container ls -all ``` >[OPTIONS] >1.列出當前所有正在運行的容器+歷史上運行過的:-a 2.顯示最近創建的容器:-l 3.顯示最近n個創建的容器:-n 4.只顯示容器編號:-q 5.不截斷輸出(完整輸出):`--no-trunc` * 查看容器內運行的進程: ``` docker top ``` * 查看容器日誌 ``` docker logs -f -t --tail 容器ID (-t:加入時間戳) (-f:跟隨最新的日製打印) (--tail 數字: 顯示後面[數字]條) ``` * 查看容器內部細節 ``` docker inspect 容器ID ``` #### 終止 * 停止退出:`exit` * 不停止退出:ctrl+P+Q * 終止一個執行中的容器:`docker stop` ``` docker start 容器名 (啟動關閉的容器) docker restart 容器名 (重新啟動容器) ``` * 強制停止容器:```docker kill 容器ID或容器名``` #### 刪除 `docker rm 容器ID`刪除一個處於終止狀態的容器 * 移除所有未使用的 Docker 項目 `docker system prune` * 移除所有沒有在使用的 Images `docker image prune -a` #### 進入容器(於後台執行時) * 外部進內部 `docker exec -it 容器ID (bash)`(-it/bash為進行互動) EX: ``` docker run -idt ubuntu 243c32535da7d142fb0e6df616a3c3ada0b8ab417937c853a9e1c251f499f550 docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 243c32535da7 ubuntu:latest "/bin/bash" 18 seconds ago Up 17 seconds nostalgic_hypatia docker exec -ti nostalgic_hypatia bash root@243c32535da7:/# ``` * 在外部向Container內執行指令(遠程操作) `docker exec 容器ID` * 進入-連接Container的標準輸出輸入端 `docker attach 容器ID` #### 其他 * 匯入匯出 * 匯出容器快照到本地檔案 ``` docker export 容器ID > 你想要的名稱.tar ``` EX: ``` $ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 7691a814370e ubuntu:14.04 "/bin/bash" 36 hours ago Exited (0) 21 hours ago test $ sudo docker export 7691a814370e > ubuntu.tar ``` * `docker import` 從容器快照檔案中再匯入為映像檔 EX: ``` $ cat ubuntu.tar | sudo docker import - test/ubuntu:v1.0 $ sudo docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE test/ubuntu v1.0 9d37a6082e97 About a minute ago 171.3 MB ``` :::warning `docker import` <font color=#FF3333>V.S.</font>`docker load` ->使用者既可以使用 docker load 來匯入映像檔儲存檔案到本地映像檔庫,也可以使用 docker import 來匯入一個容器快照到本地映像檔庫。這兩者的區別在於容器快照檔案將丟棄所有的歷史記錄和原始資料訊息(即僅保存容器當時的快照狀態),而映像檔儲存檔案將保存完整記錄,檔案體積也跟著變大。此外,從容器快照檔案匯入時可以重新指定標籤等原始資料訊息。 ::: * copy:`docker cp 路徑1 (名稱) 路徑2 ` * commit容器變更之後再做成一個映像檔 ``` docker commit提交容器副本使之成為一個新的鏡像 docker commit -m=“提交的描述訊息” -a=“作者” 容器ID 要創建的目標鏡像名:[標籤名(版本)] ``` :::info 使用commit可以推疊映像檔,通常建議一個映像檔只裝一個程式,再把映像檔一層一層疊起來以提供一個完整服務。 流程: >映像檔->容器->利用另一個映像檔在這個容器內建立容器實體->打包變成映像檔[color=red] ### 數據卷 資料卷是一個可供一個或多個容器使用的特殊目錄,它繞過 UFS,可以提供很多有用的特性: * 資料卷可以在容器之間共享和重用 * 對資料卷的修改會立馬生效 * 對資料卷的更新,不會影響映像檔 * 卷會一直存在,直到沒有容器使用 *資料卷的使用,類似於 Linux 下對目錄或檔案進行 mount。 ## dockerfile ### 一般解說 dockerfile一般分為4個部分 * 基底映像檔資訊 * 維護者資訊 * 映像檔操作指令 * 容器啟動時執行指令 ### 基本編寫(要看啦) 同一層命令可以編寫很多指令,避免太多層,指令之間要以&&隔開 如要換行一定要加\(換行符號) ### 命令 #### FROM 第一條指令必須為 `FROM` 指令 指定此image是以什麼image為基底而做的 如果在同一個Dockerfile中建立多個映像檔時,可以使用多個 FROM 指令(每個映像檔一次) ``` FROM <image> FROM <image>:<tag> ``` #### MAINTAINER 維護者資訊 ``` MAINTAINER <name> ``` #### RUN `RUN` 指令將在當前映像檔基底上執行指定命令,並產生新的映像檔。當命令較長時可以使用 `\`來換行 ``` RUN <command> RUN ["executable", "param1", "param2"] ``` 前者將在 shell 終端中運行命令,即 `bin/sh -c`;後者則使用 `exec` 執行。指定使用其它終端可以透過第二種方式實作,例如 `RUN ["/bin/bash", "-c", "echo hello"]`。 #### CMD 支援三種格式 * `CMD ["executable","param1","param2"]` 使用 exec 執行,推薦使用; * `CMD command param1 param2 在 /bin/sh 中執行`,使用在給需要互動的指令; * `CMD ["param1","param2"]` 提供給 ENTRYPOINT 的預設參數; 指定啟動容器時執行的命令,每個 Dockerfile 只能有一條 `CMD` 命令。如果指定了多條命令,只有最後一條會被執行。且`CMD`命令會被`docker run`之後的參數替換。 #### EXPOSE ``` EXPOSE <port> [<port>...] ``` 設定 Docker 伺服器容器對外的埠號,供外界使用。在啟動容器時需要透過 -P,Docker 會自動分配一個埠號轉發到指定的埠號。 #### ENV 是在build的時候,可以定義一些變數,會被後續 `RUN` 指令使用,並在容器運行時保持。 ``` ENV <key> <value> ``` [ENV用法](https://peihsinsu.gitbooks.io/docker-note-book/content/dockerfile-env-vs-arg.html) #### ADD 該命令將複製指定的 `<src>` 到容器中的 `<dest>`。 其中 `<src>` 可以是 Dockerfile 所在目錄的相對路徑;也可以是一個 URL;還可以是一個 tar 檔案(其複製後會自動解壓縮)。 ``` ADD <src> <dest> ``` [What is the Docker ADD command?](https://www.educative.io/edpresso/what-is-the-docker-add-command) #### COPY 複製本地端的 `<src>`(為 Dockerfile 所在目錄的相對路徑)到容器中的 `<dest>`。 當使用本地目錄為根目錄時,推薦使用 `COPY`。 ``` COPY <src> <dest> ``` #### ENTRYPOINT 指定容器啟動後執行的命令,並且不會被 docker run 提供的參數覆蓋。 每個 Dockerfile 中只能有一個 `ENTRYPOINT`,當指定多個時,只有最後一個會生效。 ``` ENTRYPOINT ["executable", "param1", "param2"] ENTRYPOINT command param1 param2(shell中執行)。 ``` #### VOLUME ``` VOLUME ["/data"] ``` 建立一個可以從本地端或其他容器掛載的掛載點,一般用來存放資料庫和需要保存的資料等。 #### WORKDIR ``` WORKDIR /path/to/workdir ``` 為後續的 RUN、CMD、ENTRYPOINT 指令指定工作目錄。 可以使用多個 WORKDIR 指令,後續命令如果參數是相對路徑,則會基於之前命令指定的路徑。 ### docker build dockerfile可以藉由docker build來建立image ``` docekr build [選項] 路徑 EX: docker build -t myrepo/myapp /tmp/test1/ ``` lammps範例檔案 ```shell= #centos7baseimage FROM centos:7 #download necessary document RUN yum -y update && yum -y install wget vim fftw mpich GNUmake make which locate&& yum groupinstall -y 'Development Tools' && yum clean all #openssl RUN echo 'export PATH=$PATH:/usr/lib64/mpich/bin'>>/etc/profile && \ source /etc/profile && \ mkdir /usr/local/openssl && \ cd /usr/local/openssl && \ wget https://www.openssl.org/source/openssl-1.1.1i.tar.gz && \ tar xvf openssl-1.1.1i.tar.gz && \ cd /usr/local/openssl/openssl-1.1.1i && \ ./config --prefix=/usr/local/openssl && \ make -j16 && \ make install && \ rm -rf /usr/bin/openssl && \ ln -s /usr/local/openssl/bin/openssl /usr/bin/openssl && \ ln -s /usr/local/openssl/lib/libssl.so.1.1 /usr/lib64/libssl.so.1.1 && \ ln -s /usr/local/openssl/lib/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1 && \ yum install -y openssl-devel && \ #cmake mkdir /usr/local/cmake && \ cd /usr/local/cmake/ && \ wget https://github.com/Kitware/CMake/releases/download/v3.20.0-rc2/cmake-3.20.0-rc2.tar.gz && \ tar xvf cmake-3.20.0-rc2.tar.gz && \ cd cmake-3.20.0-rc2/ && \ ./bootstrap --prefix=/usr/local/cmake && \ gmake -j16 && \ gmake install && \ ln -s /usr/local/cmake/bin/cmake /usr/bin/cmake && \ ln -s /usr/local/cmake/bin/cpack /usr/bin/cpack && \ ln -s /usr/local/cmake/bin/ctest /usr/bin/ctest && \ cmake --version && \ #lammps cd /opt &&\ git clone -b stable https://github.com/lammps/lammps.git lammps && \ cd /opt/lammps && \ mkdir /opt/lammps/build && \ cd /opt/lammps/build && \ cmake /opt/lammps/cmake && \ cmake --build . && \ echo 'export PATH=$PATH:/opt/lammps/build' >> /etc/profile && \ source /etc/profile CMD ["/bin/bash"] ```