【docker】docker虛擬容器的使用大全

Docker容器詳解

Docker是基于Go語言開發的開源應用容器引擎,遵從Apache Licence 2.0協議,可以讓開發者打包應用以及應用的依賴包到一個可移植的容器中,然后發布到各種發行版本的Linux系統上。

Docker簡介

軟件開發中最為麻煩的事情可能就是配置環境了。由于用戶使用的操作系統具有多樣性,即便使用跨平臺的開發語言(如Java和Python)都不能保證代碼能夠在各種平臺下都可以正常的運轉,而且在不同的環境下我們安裝的軟件需要依賴的軟件包也是不一樣的。

那么問題來了,我們安裝軟件的時候可不可以把軟件運行的環境一并安裝?我們是不是可以把原始環境一模一樣地復制過來呢?

虛擬機(virtual machine)就是帶環境安裝的一種解決方案,它可以在一種操作系統里面運行另一種操作系統,比如在Windows系統里面運行Linux系統,在macOS上運行Windows,而應用程序對此毫無感知。使用過虛擬機的人都知道,虛擬機用起來跟真實系統一模一樣,而對于虛擬機的宿主系統來說,虛擬機就是一個普通文件,不需要了就刪掉,對宿主系統或者其他的程序并沒有影響。但是虛擬機通常會占用較多的系統資源,啟動和關閉也非常的緩慢,總之用戶體驗并沒有想象中的那么好。

Docker屬于對Linux容器技術(LXC)的一種封裝(利用了Linux的namespace和cgroup技術),它提供了簡單易用的容器使用接口,是目前最流行的 Linux 容器解決方案。Docker將應用程序與該程序的依賴打包在一個文件里面,運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器里運行,就好像在真實的物理機上運行一樣。下圖是虛擬機和容器的對比,左邊是傳統的虛擬機,右邊是Docker。

?

目前,Docker主要用于幾下幾個方面:

  1. 提供一次性的環境。
  2. 提供彈性的云服務(利用Docker很容易實現擴容和收縮)。
  3. 實踐微服務架構(隔離真實環境在容器中運行多個服務)。

安裝Docker

下面以CentOS為例講解如何安裝Docker,使用Ubuntu、macOS或Windows的用戶可以通過點擊對應的鏈接了解這些平臺下如何進行安裝。

  1. 確定操作系統內核版本(CentOS 7要求64位,內核版本3.10+;CentOS 6要求64位,內核版本2.6+),可以通過下面的命令確定Linux系統內核版本并更新底層庫文件。
uname -r
yum update
  1. 在CentOS下使用yum安裝Docker并啟動。
yum -y install docker
systemctl start docker
  1. 查看Docker的信息和版本。
docker version
docker info

接下來可以通過下載鏡像和創建容器來看看Docker是否可以運轉起來。可以使用下面的命令從Docker的鏡像倉庫下載名為hello-world的鏡像文件。

docker pull hello-world

查看所有鏡像文件。

docker images
REPOSITORY               TAG        IMAGE ID            CREATED             SIZE
docker.io/hello-world    latest     fce289e99eb9        7 months ago        1.84 kB

通過鏡像文件創建并運行容器。

docker container run --name mycontainer hello-world

說明:其中mycontainer是我們給容器起的名字,跟在--name參數之后;hello-world就是我們剛才下載的鏡像文件。

Hello from Docker!
This message shows that your installation appears to be working correctly.To generate this message, Docker took the following steps:1. The Docker client contacted the Docker daemon.2. The Docker daemon pulled the "hello-world" image from the Docker Hub.(amd64)3. The Docker daemon created a new container from that image which runs theexecutable that produces the output you are currently reading.4. The Docker daemon streamed that output to the Docker client, which sent itto your terminal.To try something more ambitious, you can run an Ubuntu container with:$ docker run -it ubuntu bashShare images, automate workflows, and more with a free Docker ID:https://hub.docker.com/For more examples and ideas, visit:https://docs.docker.com/get-started/

如果要刪除這個容器,可以使用下面的命令。

docker container rm mycontainer

在刪除容器之后,我們還可以刪除剛才下載的鏡像文件。

docker rmi hello-world

說明:如果要在Ubuntu(內核版本3.10+)下面安裝和啟動Docker,可以按照如下的步驟進行。

apt update
apt install docker-ce
service docker start

國內用戶可以通過更換Ubuntu軟件下載源來提升下載速度,具體請參照清華大學開源軟件鏡像站上的《Ubuntu鏡像使用幫助》。

安裝Docker后,由于直接訪問dockerhub下載鏡像會非常緩慢,建議將服務器更換為國內鏡像,可以通過修改?/etc/docker/daemon.json?文件來做到。一般的云服務器會有自己專屬的鏡像,就不需要手動修改了。

{"registry-mirrors": ["http://hub-mirror.c.163.com","https://registry.docker-cn.com"]
}

使用Docker

想要玩轉Docker,最簡單的辦法就是馬上用Docker創建一些自己學習和工作中需要用到的容器,下面我們帶著大家一起來創建這些容器。

運行Nginx

Nginx是高性能的Web服務器,同時也是做反向代理服務器的上佳選擇。使用Docker可以非常簡單的創建一個運行Nginx的容器,命令如下所示。

docker container run -d -p 80:80 --rm --name mynginx nginx

說明:上面的參數-d表示容器在后臺運行(不產生輸出到Shell)并顯示容器的ID;-p是用來映射容器的端口到宿主機的端口,冒號前面是宿主機的端口,冒號后面是容器內部使用的端口;--rm表示容器停止后自動刪除容器,例如執行命令docker container stop mynginx后,容器就不復存在了;--name后面的mynginx是自定義的容器名字;在創建容器的過程中,需要用到nginx的鏡像文件,鏡像文件的下載是自動完成的,如果沒有指定版本號,默認是最新版本(latest)。

如果需要將自己的Web項目(頁面)部署到Nginx上,可以使用容器拷貝命令將指定路徑下所有的文件和文件夾拷貝到容器的指定目錄中。

docker container cp /root/web/index.html mynginx:/usr/share/nginx/html

如果不愿意拷貝文件也可以在創建容器時通過數據卷操作--volume將指定的文件夾映射到容器的某個目錄中,例如將Web項目的文件夾直接映射到/usr/share/nginx/html目錄。我們先通過下面的命令讓剛才創建的容器停止運行。

docker container stop mynginx

然后用下面的命令重新創建容器。

docker container run -d -p 80:80 --rm --name mynginx --volume /root/docker/nginx/html:/usr/share/nginx/html nginx

說明:上面創建容器和拷貝文件的命令中,container是可以省略的,也就是說docker container rundocker run是一樣的,而docker container cpdocker cp是一樣的。此外,命令中的--volume也可以縮寫為-v,就如同-d--detach的縮寫,-p--publish的縮寫。$PWD代表宿主系統當前文件夾,這些對于使用過Unix或者Linux系統的人來說,應該是很容易理解的。

要查看運行中的容器,可以使用下面的命令。

docker ps
CONTAINER ID    IMAGE    COMMAND                  CREATED            STATUS             PORTS                 NAMES
3c38d2476384    nginx    "nginx -g 'daemon ..."   4 seconds ago      Up 4 seconds       0.0.0.0:80->80/tcp    mynginx

要啟動和停止容器,可以使用下面的命令。

docker start mynginx
docker stop mynginx

由于在創建容器時使用了--rm選項,容器在停止時會被移除,當我們使用下面的命令查看所有容器時,應該已經看不到剛才的mynginx容器了。

docker container ls -a

如果在創建容器時沒有指定--rm選項,那么也可以使用下面的命令來刪除容器。

docker rm mynginx

要刪除正在運行中的容器,需要使用-f選項。

docker rm -f mynginx

運行MySQL

我們再來嘗試用Docker安裝一臺MySQL服務器,首先可以先檢查一下有沒有MySQL的鏡像文件。

docker search mysql
INDEX        NAME            DESCRIPTION        STARS        OFFICIAL        AUTOMATED
docker.io    docker.io/mysql MySQL is a ...     8486         [OK]
...

說明:上面查詢結果的列依次代表索引、鏡像名、鏡像描述、用戶評價、是否官方鏡像、自動構建。

下載MySQL鏡像并指定鏡像的版本號。

docker pull mysql:5.7

如果需要查看已經下載的鏡像文件,可以使用下面的命令。

docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io/nginx     latest              e445ab08b2be        2 weeks ago         126 MB
docker.io/mysql     5.7                 f6509bac4980        3 weeks ago         373 MB

創建并運行MySQL容器。

docker run -d -p 3306:3306 --name mysql57 -v /root/docker/mysql/conf:/etc/mysql/mysql.conf.d -v /root/docker/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7

注意:上面創建容器時我們又一次使用了數據卷操作,那是因為通常容器是隨時創建隨時刪除的,而數據庫中的數據卻是需要保留下來的。

上面的兩個數據卷操作一個是映射了MySQL配置文件所在的文件夾,一個是映射了MySQL數據所在的文件夾,這兩個數據卷操作非常重要。我們可以將MySQL的配置文件放在$PWD/mysql/conf目錄下,配置文件的具體內容如下所示:

[mysqld]
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
datadir=/var/lib/mysql
log-error=/var/log/mysql/error.log
server-id=1
log-bin=/var/log/mysql/mysql-bin.log
expire_logs_days=30
max_binlog_size=256M
symbolic-links=0

如果安裝了MySQL 8.x版本(目前的最新版本),在使用客戶端工具連接服務器時可能會遇到error 2059: Authentication plugin 'caching_sha2_password' cannot be loaded的問題,這是因為MySQL 8.x默認使用了名為“caching_sha2_password”的機制對用戶口令進行了更好的保護,但是如果客戶端工具不支持新的認證方式,連接就會失敗。解決這個問題有兩種方式:一是升級客戶端工具來支持MySQL 8.x的認證方式;二是進入容器,修改MySQL的用戶口令認證方式。下面是具體的步驟,我們先用docker exec命令進入容器的交互式環境,假設運行MySQL 8.x的容器名字叫mysql8x

docker exec -it mysql8x /bin/bash

進入容器的交互式Shell之后,可以首先利用MySQL的客戶端工具連接MySQL服務器。

mysql -u root -p
Enter password:
Your MySQL connection id is 16
Server version: 8.0.12 MySQL Community Server - GPL
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>

接下來通過SQL來修改用戶口令就可以了。

alter user 'root'@'%' identified with mysql_native_password by '123456' password expire never;

當然,如果愿意你也可以查看一下用戶表檢查是否修改成功。

use mysql;
select user, host, plugin, authentication_string from user where user='root';
+------+-----------+-----------------------+-------------------------------------------+
| user | host      | plugin                | authentication_string                     |
+------+-----------+-----------------------+-------------------------------------------+
| root | %         | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
| root | localhost | mysql_native_password | *6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9 |
+------+-----------+-----------------------+-------------------------------------------+
2 rows in set (0.00 sec)

在完成上面的步驟后,現在即便不更新客戶端工具也可以連接MySQL 8.x了。

運行Redis

接下來我們試一試運行多個容器并讓多個容器之間通過網絡通信。我們創建4個Redis容器來實現一主三從的主從復制結構。

docker run -d -p 6379:6379 --name redis-master redis
docker run -d -p 6380:6379 --name redis-slave-1 --link redis-master:redis-master redis redis-server --replicaof redis-master 6379
docker run -d -p 6381:6379 --name redis-slave-2 --link redis-master:redis-master redis redis-server --replicaof redis-master 6379
docker run -d -p 6382:6379 --name redis-slave-3 --link redis-master:redis-master redis redis-server --replicaof redis-master 6379

上面的命令中,--link參數用于給容器創建網絡別名,因為三臺從機(slave)需要通過網絡連接自己的主機(master)。雖然,我們可以通過docker inspect --format '{{ .NetworkSettings.IPAddress }}' <container-ID>命令來查看到容器的IP地址,但是由于容器的即裝即用性,容器的IP地址有可能會發生變化,如果直接使用IP地址,在容器重啟后就可能會因為IP地址的變化導致從機無法連接到主機。使用--link參數創建網絡別名就是為了在啟動Redis服務器時在redis-server后面的--replicaof參數后使用這個別名而不是IP地址。

接下來我們進入名為redis-master的容器,看看主從復制的配置是否成功。

docker exec -it redis-master /bin/bash

通過redis-cli啟動命令行工具。

redis-cli
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:3
slave0:ip=172.17.0.4,port=6379,state=online,offset=1988,lag=0
slave1:ip=172.17.0.5,port=6379,state=online,offset=1988,lag=1
slave2:ip=172.17.0.6,port=6379,state=online,offset=1988,lag=1
master_replid:94703cfa03c3ddc7decc74ca5b8dd13cb8b113ea
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:1988
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:1988

運行GitLab

GitLab是由GitLab Inc.開發的Git倉庫管理工具,具有wiki、問題跟蹤、持續集成等一系列的功能,分為社區版和企業版。通過Docker提供的虛擬化容器,我們可以安裝社區版的Docker。因為GitLab需要使用SSH協議進行安全連接,我們要暴露容器的22端口,所以可以先將宿主機SSH連接的22端口修改為其他端口(如:12345),然后再進行后續的操作。

vim /etc/ssh/sshd_config

將其中定義端口的那行代碼去掉注釋并將端口修改為12345。

Port 12345

重新啟動sshd服務。

systemctl restart sshd

提示:修改端口后應該確保防火墻上也開啟對應的端口,否則無法使用SSH連接到Linux服務器。

創建需要用于數據卷映射操作的文件夾。

mkdir -p /root/gitlab/config
mkdir -p /root/gitlab/logs
mkdir -p /root/gitlab/data

基于gitlab/gitlab-ce鏡像創建容器,并暴露80端口(HTTP連接)和22端口(SSH連接)。

docker run -d -p 80:80 -p 22:22 --name gitlab -v /root/gitlab/config:/etc/gitlab -v /root/gitlab/logs:/var/log/gitlab -v /root/gitlab/data:/var/opt/gitlab gitlab/gitlab-ce

說明:GitLab的啟動比較緩慢,創建好容器后可能需要等待一段時間才能通過瀏覽器來進行訪問。

首次進入GitLab訪問界面會提示我們修改管理員密碼,設置好管理員密碼后就可以在登錄界面輸入用戶名root和剛才設置的密碼登錄到管理員控制臺,在使用上還是非常簡單和人性化的。

構建鏡像

通過上面的講解,我們已經掌握了如何通過官方提供的鏡像來創建容器。當然如果愿意,我們也可以用配置好的容器來生成鏡像。簡而言之,Docker鏡像是由文件系統疊加而成的,系統的最底層是bootfs,相當于就是Linux內核的引導文件系統;接下來第二層是rootfs,這一層可以是一種或多種操作系統(如Debian或Ubuntu文件系統),Docker中的rootfs是只讀狀態的;Docker利用聯合掛載技術將各層文件系統疊加到一起,最終的文件系統會包含有底層的文件和目錄,這樣的文件系統就是一個鏡像。

之前我們講過了如何查找、列出鏡像和拉取(下載)鏡像,接下來看看構建鏡像的兩種方式:

  1. 使用docker commit命令。(不推薦)
  2. 使用docker build命令和Dockerfile文件。

使用commit命令構建鏡像

為了演示如何構建鏡像,我們先使用Ubuntu鏡像來定制一個容器,命令如下所示。

docker run --name myubuntu -it ubuntu /bin/bash

在容器中執行下面的命令來安裝Apache服務器并退出容器。

apt -y upgrade
apt -y install apache2
exit

我們將這個容器作為一個定制的Web服務器保存起來,當需要這樣一臺Web服務器的時候,就沒有必要重新創建容器并安裝Apache了。

首先我們通過下面的命令查看容器的ID。

docker container ls -a
docker container ls -a
CONTAINER ID    IMAGE    COMMAND        CREATED        STATUS        PORTS    NAMES
014bdb321612    ubuntu   "/bin/bash"    5 minutes ago  Exited (0)             myubuntu

提交定制的容器。

docker commit 014bdb321612 jackfrued/mywebserver

查看鏡像文件。

docker images
REPOSITORY              TAG       IMAGE ID        CREATED             SIZE
jackfrued/mywebserver   latest    795b294d265a    14 seconds ago      189 MB

生成鏡像文件以后,后面就可以利用剛才創建的鏡像文件來創建新的容器。

使用Dockerfile構建鏡像

Dockerfile使用DSL(Domain Specific Language)來構建一個Docker鏡像,只要編輯好了Dockerfile文件,就可以使用docker build命令來構建一個新的鏡像。

我們先創建一個名為myapp的文件夾來保存項目代碼和Dockerfile的文件,如下所示:

[ECS-root temp]# tree myapp
myapp
├── api
│   ├── app.py
│   ├── requirements.txt
│   └── start.sh
└── Dockerfile

其中api是Flask項目的文件夾,其中包括了項目代碼、依賴項以及啟動腳本等文件,具體內容如下所示:

app.py文件:

from flask import Flask
from flask_restful import Resource, Api
from flask_cors import CORSapp = Flask(__name__)
CORS(app, resources={r'/api/*': {'origins': '*'}})
api = Api(app)class Product(Resource):def get(self):products = ['Ice Cream', 'Chocolate', 'Coca Cola', 'Hamburger']return {'products': products}api.add_resource(Product, '/api/products')

requirements.txt文件:

flask
flask-restful
flask-cors
redis
gunicorn

start.sh文件:

#!/bin/bash
exec gunicorn -w 4 -b 0.0.0.0:8000 app:app

提示:需要給start.sh文件以執行權限,可以使用chmod 755 start.sh命令來做到。

Dockerfile文件:

# 指定基礎鏡像
FROM python:3.7
# 指定鏡像的維護者
MAINTAINER jackfrued "jackfrued@126.com"
# 將指定文件添加到容器中指定的位置
ADD api/* /root/api/
# 設置工作目錄
WORKDIR /root/api
# 執行命令(安裝Flask項目的依賴項)
RUN pip install -r requirements.txt -i https://pypi.doubanio.com/simple/
# 容器啟動時要執行的命令
ENTRYPOINT ["./start.sh"]
# 暴露端口
EXPOSE 8000

我們來解釋一下上面的Dockerfile文件。Dockerfile文件通過特殊的指令來指定基礎鏡像(FROM指令)、創建容器后需要指定的命令(RUN指令)以及需要暴露的端口(EXPOSE)等信息。我們稍后會專門為大家介紹這些Dockfile中的指令。

接下來我們可以使用docker build命令來創建鏡像,如下所示。

docker build -t "jackfrued/myapp" .

提示:上面的命令最后面的.?千萬不要漏掉了哦,它表示從當前路徑下尋找Dockerfile。

通過下面的命令可以查看創建好的鏡像。

docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
jackfrued/myapp              latest              6d6f026a7896        5 seconds ago       930 MB

如果想知道鏡像文件是如何創建出來的,可以使用下面的命令。

docker history jackfrued/myapp
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
6d6f026a7896        31 seconds ago      /bin/sh -c #(nop)  EXPOSE 8000/tcp              0 B                 
3f7739173a79        31 seconds ago      /bin/sh -c #(nop)  ENTRYPOINT ["./start.sh"]    0 B                 
321e6bf09bf1        32 seconds ago      /bin/sh -c pip install -r requirements.txt...   13 MB               
2f9bf2c89ac7        37 seconds ago      /bin/sh -c #(nop) WORKDIR /root/api             0 B                 
86119afbe1f8        37 seconds ago      /bin/sh -c #(nop) ADD multi:4b76f9c9dfaee8...   870 B               
08d465e90d4d        3 hours ago         /bin/sh -c #(nop)  MAINTAINER jackfrued "j...   0 B                 
fbf9f709ca9f        12 days ago         /bin/sh -c #(nop)  CMD ["python3"]              0 B 

使用該鏡像來創建容器運行Web服務器。

docker run -d -p 8000:8000 --name myapp jackfrued/myapp

如果希望將上面創建的鏡像文件放到dockerhub倉庫中,可以按照如下所示的步驟進行操作。

通過下面的命令登錄到dockerhub。

docker login

輸入用戶名和口令進行登錄。

Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: jackfrued
Password: 
Login Succeeded

通過下面的命令將鏡像推到倉庫中。

docker push jackfrued/webserver

dockerhub-repo.pnguploading.4e448015.gif轉存失敗重新上傳取消

Dockerfile指令

想了解Dockerfile的指令可以查看官方提供的參考手冊,下面我們為大家介紹一些常用的指令。

  1. FROM:設置基礎鏡像,必須是Dockerfile中的第一條指令。

    FROM <鏡像名> [AS <別名>]

    FROM <鏡像名>[:<標簽>] [AS <別名>]
  2. RUN:指定構建鏡像時要執行的命令。

    RUN <命令> [參數1], [參數2], ... 

    RUN ["可執行文件", "參數1", "參數2", ...]
  3. CMD:指定構建鏡像后要執行的命令。

    CMD <命令> [參數1], [參數2], ...

    CMD ["可執行文件", "參數1", "參數2", ...]

    說明:Docker不同于虛擬機,容器本身就是一個進程,容器中的應用應該位于前臺運行。CMD命令相當于就是用來指定容器主進程(創建容器后要在前臺執行的程序)的,如果主進程結束了,容器也就停止運行了。所以在容器中啟動Nginx不能使用service nginx start或是systemctl start nginx而是要通過CMD ["nginx", "-g", "daemon off;"]讓它在前臺運行。

  4. ENTRYPOINT:和CMD類似,也可以執行命令,但docker run命令行中指定的任何參數都會被當做參數再次傳給ENTRYPOINT指令中的命令,這就使得我們可以構建一個鏡像,它既可以運行一個默認的命令,也支持通過docker run命令行為該命令指定可覆蓋的參數選項。

    ENTRYPOINT <命令> [參數1], [參數2], ...

    ENTRYPOINT ["可執行文件", "參數1", "參數2", ...]
  5. WORKDIR:在通過鏡像創建新容器時,在容器內部創建一個工作目錄,ENTRYPOINT和CMD指定的程序會在這個目錄下執行。在使用docker run命令時可以通過-w參數來覆蓋由WORKDIR指定的工作目錄。例如:

    WORKDIR /opt/webapp
    docker run -w /usr/share/webapp ...
  6. ENV:在創建鏡像時設置環境變量。在使用docker run命令時,可以通過-e參數來修改環境變量的設置。例如:

    ENV DEFAULT_PORT=8080
    docker run -e "DEFAULT_PORT=8000" ...
  7. USER:指定鏡像會以什么用戶身份去運行。例如:

    USER nginx
  8. VOLUME:在創建容器時添加一個數據卷的掛載點。通過數據卷操作可以實現容器間數據的共享和重用,對卷所作的修改可以馬上生效而不需要重新啟動容器,我們之前創建容器時使用--volume參數就是為了實現數據卷的映射操作。

    VOLUME ["/路徑1", "/路徑2/子路徑2.1/", ...]
  9. ADD:將構建目錄下的文件和文件夾復制到鏡像中,如果是壓縮文件和歸檔文件,ADD命令會對這些文件進行解壓縮解歸檔的操作。

    ADD [--chown=<用戶>:<用戶組>] <源文件> <目標文件>
  10. COPY:非常類似于ADD,但不會主動對文件進行提取操作。

  11. LABEL:為Docker鏡像添加一些元數據,在使用docker inspect命令時會看到這些元數據。

    LABEL version="1.0.0" location="Chengdu"
  12. ONBUILD:為鏡像添加觸發器,當一個鏡像被用作其他鏡像的基礎鏡像,觸發器將會被執行。例如:

    ONBUILD ADD . /app/src
    ONBUILD RUN cd /app/src && make

多容器管理

我們的項目可能會使用了多個容器,容器多了之后管理容器的工作就會變得麻煩。如果要對多個容器進行自動配置使得容器可以相互協作甚至實現復雜的調度,這就需要進行容器編排。Docker原生對容器編排的支持非常弱,但是可以通過社區提供的工具來實現容器編排。

Docker Compose

可以通過安裝Docker Compose工具來實現基于YAML文件的容器編排,YAML文件會定義一系列的容器以及容器運行時的屬性,Docker Compose會根據這些配置來管理容器。

  1. 安裝Docker Compose。

    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

    說明:如果沒有curl工具,在CentOS下可以先通過包管理工具yum安裝curl再執行上面的命令。

    當然我們也可以使用Python的包管理工具pip來安裝Docker Compose,命令如下所示。

    pip3 install -U docker-compose
  2. 使用Docker Compose。

    我們在剛才的Flask項目中引入緩存,然后再利用Flask提供的數據接口為前端頁面提供數據,使用Vue.js進行頁面渲染并將靜態頁面部署在Nginx服務器上。項目文件夾結構如下所示:

    [ECS-root ~]# tree temp
    temp
    ├── docker-compose.yml
    ├── html
    │   └── index.html
    └── myapp├── api│   ├── app.py│   ├── requirements.txt│   └── start.sh└── Dockerfile

    修改后的app.py文件代碼如下所示:

    from pickle import dumps, loadsfrom flask import Flask
    from flask_restful import Resource, Api
    from flask_cors import CORS
    from redis import Redisapp = Flask(__name__)
    CORS(app, resources={r'/api/*': {'origins': '*'}})
    api = Api(app)
    redis = Redis(host='redis-master', port=6379)class Product(Resource):def get(self):data = redis.get('products')if data:products = loads(data)else:products = ['Ice Cream', 'Chocolate', 'Coca Cola', 'Hamburger']redis.set('products', dumps(products))return {'products': products}api.add_resource(Product, '/api/products')

    html文件夾用來保存靜態頁面,稍后我們會通一個運行Nginx的容器來向瀏覽器提供靜態頁面。index.html文件的內容如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="utf-8"><title>首頁</title>
    </head>
    <body><div id="app"><h2>產品列表</h2><ul><li v-for="product in products">{{ product }}</li></ul></div><script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script><script>new Vue({el: '#app', data: {products: []},created() {fetch('http://1.2.3.4:8000/api/products').then(resp => resp.json()).then(json => {this.products = json.products})}})</script>
    </body>
    </html>

    接下來,我們要通過docker-compose.yml文件來創建三個容器并指明容器之間的依賴關系。

    version: '3'
    services:api-server:build: ./myappports:- '8000:8000'links:- redis-masterweb-server:image: nginxports:- '80:80'volumes:- ./html:/usr/share/nginx/htmlredis-master:image: redisexpose:- '6379'

    有了這個YAML文件,我們就可以使用docker-compose命令來創建容器運行項目,其命令如下所示:

    [ECS-root temp]# docker-compose up
    Creating network "temp_default" with the default driver
    Creating temp_web-server_1   ... done
    Creating temp_redis-master_1 ... done
    Creating temp_api-server_1   ... done
    Attaching to temp_redis-master_1, temp_web-server_1, temp_api-server_1
    redis-master_1  | 1:C 05 Dec 2019 11:57:26.828 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    redis-master_1  | 1:C 05 Dec 2019 11:57:26.828 # Redis version=5.0.6, bits=64, commit=00000000, modified=0, pid=1, just started
    redis-master_1  | 1:C 05 Dec 2019 11:57:26.828 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
    redis-master_1  | 1:M 05 Dec 2019 11:57:26.830 * Running mode=standalone, port=6379.
    redis-master_1  | 1:M 05 Dec 2019 11:57:26.831 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
    redis-master_1  | 1:M 05 Dec 2019 11:57:26.831 # Server initialized
    redis-master_1  | 1:M 05 Dec 2019 11:57:26.831 # WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
    redis-master_1  | 1:M 05 Dec 2019 11:57:26.831 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
    redis-master_1  | 1:M 05 Dec 2019 11:57:26.831 * Ready to accept connections
    api-server_1    | [2019-12-05 11:57:27 +0000] [1] [INFO] Starting gunicorn 20.0.4
    api-server_1    | [2019-12-05 11:57:27 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
    api-server_1    | [2019-12-05 11:57:27 +0000] [1] [INFO] Using worker: sync
    api-server_1    | [2019-12-05 11:57:27 +0000] [8] [INFO] Booting worker with pid: 8
    api-server_1    | [2019-12-05 11:57:27 +0000] [9] [INFO] Booting worker with pid: 9
    api-server_1    | [2019-12-05 11:57:27 +0000] [10] [INFO] Booting worker with pid: 10
    api-server_1    | [2019-12-05 11:57:27 +0000] [11] [INFO] Booting worker with pid: 11

    要停止容器的運行,可以使用下面的命令。

    docker-compose down

Kubernetes

實際的生產環境中常常需要部署和管理多個協同工作的容器,docker compose解決了多容器創建和管理的問題,但是實際項目中,我們還需要Kubernetes(以下都簡稱為K8S)來提供一個跨主機集群的容器調度平臺。K8S可以進行自動化容器的部署、擴展和操作,從而提供以容器為中心的基礎架構。該項目是谷歌在2014年啟動的項目,建立在谷歌公司十余年運維經驗的基礎之上,而且谷歌自己的應用也是運行在容器上的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/455942.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/455942.shtml
英文地址,請注明出處:http://en.pswp.cn/news/455942.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【樹莓派】修改樹莓派盒子MAC地址

用樹莓派盒子&#xff0c;在某些客戶方實施過程中&#xff0c;不同客戶的網絡環境對樹莓派盒子的要求不同&#xff0c;網絡管理配置要求MAC地址和IP綁定。 一種情況下&#xff0c;查詢盒子的MAC地址&#xff0c;添加到網絡管理的路由規則中即可&#xff1b; 另一種情況下&#…

編程隨想 關系圖_IT什么崗位比較好找工作?一張金字塔圖就能明白

IT(Internet Technology)互聯網技術是指在計算機技術的基礎上開發建立的一種信息技術。IT行業這些年一直很火爆&#xff0c; 對于IT就業崗位的選擇一直也都是熱門話題。一、IT人才總體供需金字塔型人才需求和市場供應關系圖&#xff1a;人才供需圖一般IT 行業供需關系可以比喻為…

諾基亞收購了阿朗:那與 TCL 的“阿爾卡特”品牌授權協議到期后咱辦?

在被諾基亞收購之后&#xff0c;“阿爾卡特-朗訊”的牌子算是被這家芬蘭公司收入囊中。尷尬的是&#xff0c;TCL 很早就獲得了“阿爾卡特”這個智能手機品牌的授權。當然&#xff0c;對于因為錯抱了微軟 Windows Phone 這條大腿、以致于多年后再借著 HMD Global 重返 Android 智…

【Django】django使用原生SQL的方法(附加說說為什么ORM上不了大臺面)

執行自定義SQL語言&#xff1a; from django.db import connection ? cursorconnection.cursor() ? # 插入操作 cursor.execute("insert into hello_author(name) values(傳說中的申小五)") ? # 更新操作 cursor.execute("update hello_author set nameabc w…

[熵編碼] 指數哥倫布編碼

規定語法元素的編解碼模式的描述符如下&#xff1a;比特串&#xff1a;b(8):任意形式的8比特字節&#xff08;就是為了說明語法元素是為8個比特&#xff0c;沒有語法上的含義&#xff09;f(n):n位固定模式比特串&#xff08;其值固定&#xff0c;如forbidden_zero_bit的值恒為0…

python學習筆記 - lambda 與 函數嵌套

# 函數嵌套 #函數內包含函數 def fun1(a):def funa(a):return a **2def funb(a):return a **3return funa(a) funb(a)print(函數嵌套:{}:.format(fun1(3)))# lambda表達式代替嵌套函數 #lambda表達式替代嵌套函數 def fun2(a):f1 lambda a : a ** 2f2 lambda a : a ** 3re…

python編輯器_沒有人比它更懂少兒編程,慧編程Python'吮指編輯器'

咳咳&#xff01;大家好&#xff0c;我是偶爾寫文章的康康老師。今天跟大家介紹的是慧編程家的&#xff0c;睡在Scratch上鋪的兄弟——慧編程Python編輯器。這是一款集才華和顏值為一體的吮指編輯器&#xff01;忘記肯德基&#xff0c;你的手指應該為編程而生&#xff01;話不多…

微軟Scott CIO也要代表公司拜訪客戶

作為全球IT巨頭的CIO&#xff0c;微軟公司副總裁兼首席信息官Tony Scott的工作與眾不同。除了要擔任普通CIO需要擔任的角色以外&#xff0c;他還要與客戶保持溝通&#xff0c;同時還與微軟產品和研發團隊緊密聯系。正因為如此&#xff0c;Tony Scott對CIO的職責有著更深刻的理解…

HTML中的圖片

HTML圖片 html圖片 <img>標簽可以在網頁上插入一張圖片&#xff0c;它是獨立使用的標簽&#xff0c;通過“src”屬性定義圖片的地址&#xff0c;通過“alt”屬性定義圖片加載失敗時顯示的文字&#xff0c;以及對搜索引擎和盲人讀屏軟件的支持。 <img src"ima…

【Python代碼篇】-單例模式(五種實現單利方式)

&#xff08;一&#xff09;、如何反序的迭代一個序列&#xff1f; # 如果是一個list,最來的解決方案是tempList [1,2,3,4] tempList.reverse() for x in tempList:print x # 如果不是一個list,最通用的解決方案 print \n- - - - - - - - - - - - tempTuple (1,2,3,4) f…

淺談數據庫索引

1.什么是索引 數據庫索引好比是一本書前面的目錄&#xff0c;能加快數據庫的查詢速度。 例如這樣一個查詢&#xff1a;select * from table1 where id44。如果沒有索引&#xff0c;必須遍歷整個表&#xff0c;直到ID等于44的這一行被找到為止;有了索引之后(必須是在ID這一列上建…

iphone屏幕突然變暗_如果你的iPhone屏幕突然變暗,可以這樣解決

??如果在使用 iPhone 的過程中&#xff0c;屏幕忽然變暗&#xff0c;可能有如下原因&#xff1a;開啟了“亮度自動調節”功能在 iPhone 中有一項“亮度自動調節”的功能&#xff0c;此功能是根據設備周圍的光線條件來調整亮度級別&#xff1a;在光線較暗的地方&#xff0c;傳…

宏塊與宏塊對(附圖)

宏塊與宏塊對&#xff08;附圖&#xff09; 假設 A、B 是上下相鄰的兩個 MB&#xff1a;在非宏塊對的情況下&#xff1a;A、B宏塊序號不連續&#xff0c;相差圖像一行宏塊個數。即按光柵掃描順序編號。在幀宏塊對的情況下&#xff1a;A、B宏塊序號連續&#xff0c;即按鋸齒掃描…

農業部部署農業大數據發展工作 評:對農業現代化很重要

據中國鄉村之聲《三農中國》報道&#xff0c;近日&#xff0c;農業部近日印發了《關于推進農業農村大數據發展的實施意見》&#xff0c;全面部署農業農村大數據發展工作。 《意見》明確了農業農村大數據發展和應用的五大基礎性工作和十一個重點領域&#xff0c;包括夯實國家農業…

HTML中的鏈接

HTML鏈接 <a>標簽可以在網頁上定義一個鏈接地址&#xff0c;通過href屬性定義跳轉的地址&#xff0c;通過title屬性定義鼠標懸停時彈出的提示文字框。 <a href"#"></a> <!-- # 表示鏈接到頁面頂部 --> <a href"http://www.itxdl.…

【MySQL】Linux端-實現Mysql數據定時自動備份

Linux端-實現Mysql數據定時自動備份 創建存放備份 sql 的文件夾 備份數據盡量存放在Linux單獨掛載的磁盤上&#xff0c;保證數據可靠性。磁盤建議使用EXT4分區格式。 [rootlocalhost ~]# mkdir /sk/mysqlBackup測試命令行備份數據庫 [rootlocalhost ~]# /usr/bin/mysqldump --o…

視頻測試序列的下載地址

1、http://www.tkn.tu-berlin.de/research/vid/&#xff08;此網站已經移走&#xff0c;正在尋找。&#xff09; CIF&#xff1a; Akiyo、Bridge (far) 、Bridge (close) 、Bus 、Container 、Coastguard 、Flower 、Football 、Foreman 、Hall 、Highway 、Mobile & Cal…

xtrabackup遷移單獨一張INNODB表

轉載于:https://www.cnblogs.com/llguanli/p/6746130.html

c語言有趣代碼_為什么C語言永遠不會過時?

直至今天還有人在喊著C語言都過時的語言了&#xff0c;還有什么值得去學的&#xff0c;看現在的python&#xff0c;php等語言現在用起來多簡單&#xff0c;誰還去學習老掉牙的C語言&#xff0c;事實真的是這樣的嗎&#xff1f;筆者作為專門下載了這兩種語言的底層源碼。由于篇幅…

Pokemon Go將在日本發布 網絡安全公司呼吁防范虛假軟件

據《每日新聞》報道&#xff0c;手游《Pokemon Go》(精靈寶可夢Go)在海外人氣爆棚&#xff0c;日本國內也有望近日發布。日本網絡安全公司呼吁&#xff0c;在正式發布前需防范虛假游戲軟件。 美國英特爾集團邁克菲公司&#xff08;東京都澀谷區&#xff09;表示&#xff0c;《P…