沒有人不愛惜他的生命,但不多人珍視他的時間。 —— 梁實秋php
Docker 自 2013 年發佈至今一直備受關注,從招聘面試角度來看有些職位對於瞭解 Docker、K8S 這些也有一些加分項,同時學習 Docker 也是後續學習 K8S 的基礎,可是對於 Docker 不少人也需並不瞭解,其實 Docker 也並無那麼難,本文從 Docker 入門到應用實踐爲你們進行講解,中間也列舉了不少實例,但願能幫助你們更好的理解。html
做者簡介:五月君,Nodejs Developer,熱愛技術、喜歡分享的 90 後青年,公衆號「Nodejs技術棧」,Github 開源項目 www.nodejs.rednode
本篇 Docker 入門到實踐路線圖以下所示mysql
Docker 能夠將應用以集裝箱的方式進行打包,經過鏡像的方式能夠實如今不一樣的環境下進行快速部署,在團隊中還可實現一次打包,屢次共享,使用 Docker 能夠輕鬆的爲任何應用建立一個輕量級的、可移植的、自給自足的容器。linux
例如,咱們在本地將編譯測試經過的程序打包成鏡像,能夠快速的在服務器環境中進行部署,有時也能解決不一樣的開發環境形成的問題 「明明我本地是好的,可是一到服務器就不行」。nginx
爲何要使用 Docker?總結下來其有如下優勢:git
中間部位爲咱們進行 Docker 操做的宿主機,其運行了一個 Docker daemon 的核心守護程序,負責構建、運行和分發 Docker 容器。github
左邊爲 Docker 客戶端,其與 Docker 守護進程進行通訊,客戶端會將 build、pull、run 命令發送到 Docker 守護進程進行執行。web
右邊爲 Docler 註冊表存儲 Docker 鏡像,是一個全部 Docker 用戶共享 Docker 鏡像的服務,Docker daemon 與之進行交互。面試
參考 docs.docker.com/engine/dock…
什麼是 Docker 鏡像
Docker 會把應用程序及依賴打包進鏡像(Images)裏,提供了容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些爲運行時準備的一些配置參數(如匿名卷、環境變量、用戶等),經過這個鏡像文件可生成 Docker 容器。
例如:這個鏡像文件包含了一個完整的 Ubuntu 系統,咱們能夠在 Ubuntu 鏡像基礎之上安裝了 Redis、Mysql 等其它應用程序,能夠回顧下 Docker 架構一瞥 在 DOCKER_HOST 裏面有個 images。
另外在製做好鏡像文件以後能夠拷貝到其它機器使用,它是通用的,鏡像的製做能夠基於 Dockerfile 構建後面會講解。
什麼是 Docker 容器
容器是鏡像的可運行實例,你可使用 Docker API 建立、啓動、中止、移動或刪除它,
在默認狀況下,容器與其它容器及其主機是隔離的,擁有本身的獨立進程空間、網絡配置。
容器由其鏡像以及在建立或啓動容器時提供的任何配置選項定義。當容器被刪除時,對其狀態的任何未存儲在持久存儲中的更改都會消失。
Docker 是一個開源的商業產品,提供了社區版(CE)和企業版(EE),如下也都是基於企業版進行介紹,我這裏操做系統採用的 Linux 下 Ubuntu 系統,更多安裝方式也可參照官網安裝指南 docs.docker.com/install/
這個看狀況,由於 Docker 的源在國外,國內訪問速度可能會不穩定,有須要的能夠按照如下步驟更換爲國內源
$ sudo vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
複製代碼
$ sudo service docker restart
複製代碼
sudo apt-get update
複製代碼
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
複製代碼
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
複製代碼
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) \ stable"
複製代碼
sudo apt-get update
複製代碼
sudo apt-get install docker-ce docker-ce-cli containerd.io
複製代碼
執行如下命令使用腳本自動安裝,這也是最簡化的安裝流程,它會檢測你當前使用的 Linux 版本,選擇合適的安裝包進行安裝,
sudo wget -qO- https://get.docker.com | sh
複製代碼
因爲 Docker 操做須要擁有 root 權限,爲避免每次都輸入 sudo,能夠把用戶加入 Docker 用戶組,執行如下命令
# https://docs.docker.com/install/linux/linux-postinstall/#manage-docker-as-a-non-root-user
$ sudo usermod -aG docker $USER
複製代碼
安裝完成後,運行下面的命令,驗證是否安裝成功
$ docker -v
Docker version 19.03.2, build 6a30dfc
複製代碼
上面對 Docker 的鏡像和容器作了簡要概述,有個初步的瞭解以後,再來看下 Docker 鏡像和容器的實踐。
hello-world 爲鏡像名字,docker image pull 爲抓取鏡像命令,Docker 官方提供的 image 文件都放在 library 默認組裏,library/hello-world 也就爲 image 文件的位置。
$ docker image pull hello-world
# 如下爲抓取過程當中的日誌信息
Using default tag: latest
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:451ce787d12369c5df2a32c85e5a03d52cbcef6eb3586dd03075f3034f10adcd
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest
複製代碼
image 文件抓取成功經過 docker images 或 docker image ls 命令查看當前都有哪些鏡像
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 8 months ago 1.84kB
複製代碼
執行 docker container run
命令會生成一個正在運行的容器實例,另外 docker container run
發現本地沒有指定的 image 文件,其自身還有自動抓取 image 文件功能,就是上面講解的 docker image pull
命令
$ docker container run hello-world
Hello from Docker!
# 如下內容省略
...
複製代碼
使用 docker ps
或 docker container ls
命令用來查看正在運行的容器列表,這個時候是沒有正在運行的容器實例的,由於在以上 docker container run hello-world
命令執行以後 hello-world
就會中止,容器也會隨着自動中止,但並非全部的容器運行以後也都會中止的,例如 Nginx 後面會進行實踐。
$ docker ps
複製代碼
經過 docker ps --all
或 docker container ls --all
命令能夠查看全部的容器實例,包含已經中止的
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a662ec198a83 hello-world "/hello" 10 minutes ago Exited (0) 10 minutes ago exciting_wing
複製代碼
如下命令會用 nginx 鏡像啓動一個容器,命名爲 nginxserver,並映射到 8081 端口
$ docker container run --name nginxserver -d -p 8081:80 nginx
複製代碼
好了,咱們如今就可使用 http://localhost:8081/ 來訪問這個 Nginx 服務器,因爲我這裏是在虛擬機上安裝的 Docker 所以要使用個人虛擬機地址 http://192.168.6.128:8081/ 進行訪問,一樣若是你是在虛擬機、雲服務器上安裝的 Docker 也要使用相應的 ip 來訪問,若是是在本機直接 localhost 就能夠。如下爲 Nginx 默認的歡迎頁面。
再分別看下目前的 image 列表和正在運行的容器
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 5a3221f0137b 3 weeks ago 126MB
hello-world latest fce289e99eb9 8 months ago 1.84kB
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7bf26745b3f nginx "nginx -g 'daemon of…" 23 minutes ago Up 23 minutes 0.0.0.0:8081->80/tcp nginxserver
複製代碼
經過 docker container kill [containID]
命令終止正在運行的容器
# docker container kill [containID]
$ docker container kill b7bf26745b3f
複製代碼
上面的終止容器並不會刪除容器文件,僅僅是容器中止運行,經過 docker ps --all 命令查看全部的容器列表
$ docker ps --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7bf26745b3f nginx "nginx -g 'daemon of…" 29 minutes ago Exited (137) About a minute ago nginxserver
a662ec198a83 hello-world "/hello" 49 minutes ago Exited (0) 49 minutes ago exciting_wing
複製代碼
因爲已經終止容器文件依然會佔據着咱們的磁盤空間,在不使用的狀況可經過 docker container rm [containerID]
命令刪除
$ docker container rm b7bf26745b3f a662ec198a83
複製代碼
執行以上命令以後,再使用 docker ps --all
命令,此時容器列表就爲空了。
一樣刪除一個鏡像文件也很簡單執行 docker rmi [imageID]
命令便可
$ docker rmi 5a3221f0137b fce289e99eb9
複製代碼
Dockerfile 是由一系列的參數、命令構成的可執行腳本,用來構建、定製 Docker 鏡像。本節經過一個 Node.js 的簡單項目爲例,介紹下如何編寫 Dockerfile 文件、如何在 Docker 容器裏運行 Node.js 項目。
/usr/src/nodejs/hello-docker 目錄下新建 app.js
// /usr/src/nodejs/hello-docker/app.js
const http = require('http');
const PORT = 30010;
const server = http.createServer((req, res) => {
res.end('Hello Docker');
})
server.listen(PORT, () => {
console.log('Running on http://localhost:', PORT);
});
複製代碼
/usr/src/nodejs/hello-docker 目錄下新建 package.json
// /usr/src/nodejs/hello-docker/package.json
{
"name": "hello-docker",
"version": "1.0.0",
"description": "",
"author": "May",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
}
}
複製代碼
首先在項目根目錄下建立 .dockerignore 文件,把不須要打包進 Docker Image 裏的文件進行過濾
# /usr/src/nodejs/hello-docker/.dockerignore
.git
node_modules
複製代碼
Dockerfile
項目根目錄下新建 Dockerfile 文件
# /usr/src/nodejs/hello-docker/Dockerfile
FROM node:10.0
# 在容器中建立一個目錄
RUN mkdir -p /usr/src/nodejs/
# 定位到容器的工做目錄
WORKDIR /usr/src/nodejs/
# RUN/COPY 是分層的,package.json 提早,只要沒修改,就不會從新安裝包
COPY package.json /usr/src/app/package.json RUN cd /usr/src/app/ RUN npm i
# 把當前目錄下的全部文件拷貝到 Image 的 /usr/src/nodejs/ 目錄下
COPY . /usr/src/nodejs/
EXPOSE 30010
CMD npm start 複製代碼
Dockerfile 文件建立好以後,使用 docker image build
命令建立鏡像文件,-t 參數用來指定鏡像的文件名稱,最後一個 . 也不要省略,表示 Dockerfile 文件的所在目錄
$ docker image build -t hello-docker .
複製代碼
執行以上命令以後,咱們來查看下新生成的鏡像文件 hello-docker
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-docker latest 6b1c2775591e 4 minutes ago 675MB
node 10.0 1c1272350058 16 months ago 675MB
複製代碼
鏡像構建成功以後經過 docker container run 命令來生成一個容器,幾個參數說明:
$ docker container run -d -p 30000:30010 hello-docker
複製代碼
執行以上命令以後經過 docker ps 查看咱們剛剛運行的容器信息
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c2891d477edf hello-docker "/bin/sh -c 'npm sta…" 15 seconds ago Up 14 seconds 0.0.0.0:30000->30010/tcp pedantic_mestorf
複製代碼
不出什麼意外,此時咱們的 Node.js 服務已經運行在 Docker 容器的虛擬環境裏了,訪問 curl http://localhost:30000
能夠進行測試。
$ curl http://localhost:30000
Hello Docker
複製代碼
查看運行日誌,「c2891d477edf」 爲容器 ID
$ docker logs -f c2891d477edf
> hello-docker@1.0.0 start /usr/src/nodejs/hello-docker
> node app.js
Running on http://localhost: 30010
複製代碼
爲了方便排查內部容器文件,能夠經過 docker exec -it c2891d477edf /bin/sh 命令進入容器,c2891d477edf 爲容器 ID
$ docker exec -it c2891d477edf /bin/sh
$ ls # 列出目錄列表
Dockerfile app.js package-lock.json package.json
複製代碼
因爲咱們已經啓動了 hello-docker 這個服務,在容器裏再次操做 node app.js 就會報端口衝突
$ node app
events.js:167
throw er; // Unhandled 'error' event
^
Error: listen EADDRINUSE :::30010
複製代碼
按下 Ctrl + d (或者輸入 exit)退出容器
Registry 是一個註冊服務器,是一個集中存放鏡像倉庫的地方,這裏着重介紹下 Docker Hub,它是官方維護的一個公共倉庫,咱們的大部分需求也均可從這裏下載。
在開始以前你須要先去 Docker 官網註冊一個帳號 hub.docker.com/ 後續講解發布鏡像須要用到
使用 docker search 鏡像名稱
能夠搜索你須要的鏡像,搜索結果會根據 STARS 進行排序
$ docker search nginx
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
nginx Official build of Nginx. 11935 [OK]
jwilder/nginx-proxy Automated Nginx reverse proxy for docker con… 1651 [OK]
richarvey/nginx-php-fpm Container running Nginx + PHP-FPM capable of… 740 [OK]
...
複製代碼
搜索到須要的鏡像後執行 docker pull 命令拉取鏡像
$ docker pull nginx
複製代碼
$ docker login
複製代碼
# docker image tag [imageName] [username]/[repository]:[tag]
$ docker image tag hello-docker mayjun/hello-docker
複製代碼
# docker image push [username]/[repository]:[tag]
$ docker image push mayjun/hello-docker
複製代碼
鏡像發佈成功以後,在本身的我的用戶下也能夠看到鏡像信息
若是你想在別的機器上也使用這個鏡像,直接 docker pull 拉取便可,實現鏡像的共享。
Compose 是 Docker 官方開源的一個項目,能夠管理多個 Docker 容器組成一個應用,例如 Web 服務,除了服務自己還有數據庫、Redis、Nginx 等一系列相關聯服務須要安裝。
有個 Compose 的支持,咱們只須要定義一個 YAML 格式的配置文件(docker-compose.yml
),來編寫一個項目所須要的多個容器配置及調用關係,經過簡單的命令便可同時開始或者關閉這些容器。
# compose 下載以後經過管道的方式輸入至 /usr/local/bin/docker-compose
# uname -s 查找是什麼系統,例如:Linux
# uname -m 查找是什麼版本,例如:x86_64
$ curl -L https://github.com/docker/compose/releases/download/1.25.0-rc2/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 把這個文件變成可執行的
$ chmod +x /usr/local/bin/docker-compose
複製代碼
查看安裝是否成功
$ docker-compose --version
docker-compose version 1.25.0-rc2, build 661ac20e
複製代碼
WordPress 是一個免費開源的我的博客系統,使用的也是比較多的,而且也有 Docker 鏡像,使用 Docker 部署仍是很是簡單的。
在 /usr/src/wordpress 目錄下,創建 docker-compose.yml 配置文件,寫入以下內容:
mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=wordpress
web:
image: wordpress
links:
- mysql
environment:
- WORDPRESS_DB_PASSWORD=123456
ports:
- "192.168.6.128:8080:80"
working_dir: /var/www/html
volumes:
- wordpress:/var/www/html
複製代碼
啓動容器,瀏覽器輸入 http://192.168.6.128:8080 便可看到效果,能夠親自實踐下
# -d 參數表示後臺啓動
$ docker-compose up -d
複製代碼
關閉容器,執行如下命令須要在 docker-compose.yml 配置文件同級目錄下
$ docker-compose stop
複製代碼
本文是做者 「五月君」 在實踐 Docker 過程當中的一些知識總結,剛開始也是從零開始的,若是你想學習 Docker 不知道該如何入手,能夠參考本文,後續還會有 Docker 在應用程序中的實踐分享,感興趣的能夠關注公衆號 「Nodejs技術棧」 Github: github.com/Q-Angelo/No… 獲取最新消息