前言:

废话就不说了,抓紧时间学习。docker yyds!

一、Docker 概述:

Docker简介:

请添加图片描述
Docker 是一个开源的应用容器引擎,可以将你的开发环境、代码、配置文件等一并打包到这个容器中,并发布和应用到任意平台。比如,你在本地用 Python 开发网站后台,开发测试完成后,就可以将 Python3 及其依赖包、Flask 及其各种插件、Mysql、Nginx 等打包到一个容器中,然后部署到任意你想部署到的环境。

Docker 的思想来自于集装箱,集装箱解决了什么问题?在一艘大船上,可以把货物规整的摆放起来。并且各种各样的货物被集装箱标准化了,集装箱和集装箱之间不会互相影响。那么就不需要专门运送水果的船和专门运送化学品的船了。

Docker基于Go语言开发的开源项目。

对比传统虚拟机:

在容器技术出来之前,我们都是使用虚拟机技术,虚拟机相较于 docker 容器很笨重。
在这里插入图片描述

Docker 为什么比 VM 快?

1、Docker 有着比虚拟机更少的抽象层。由于 docker 不需要 Hypervisor 实现硬件资源虚拟化,运行在 docker 容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。

2、docker 利用的是宿主机的内核,vm 需要 Guest OS

  • GuestOS: VM(虚拟机)里的的系统(OS)
  • HostOS:物理机里的系统(OS)
    在这里插入图片描述

因此,当新建一个容器时,docker 不需要和虚拟机一样重新加载一个操作系统内核。虚拟机加载 GuestOS,是分钟级别的。而 docker 直接利用宿主机的操作系统,省略了这个复杂的过程,因此新建一个 docker 容器只需要几秒钟。

二、基本概念:

Docker 包括三个基本概念:

  • 镜像(Image)
  • 容器(Container)
  • 仓库(Repository)

理解了这三个概念,就理解了 Docker 的整个生命周期。

1、镜像 (image)

类似于虚拟机中的镜像,是一个包含有文件系统的面向 docker 引擎的只读模板。任何应用程序运行都需要环境,而镜像就是用来提供这种运行环境的。例如一个 Ubuntu 镜像就是一个包含 Ubuntu 操作系统环境的模板。

2、容器 (container)

镜像和容器的关系,就像是面向对象程序设计中的 “类” 和 “实例” 一样,镜像是静态的定义,容器是镜像运行时的实体。可以将其看作一个简易的Linux系统 以及运行在其中的应用程序。Docker利用容器来运行、隔离各个应用。容器是镜像创建的应用实例,可以创建、启动、停止、删除容器,各个容器之间是是相互隔离的,互不影响。

3、仓库 (repository)

仓库就是用来集中存放镜像文件的地方。类似于代码仓库,这里是镜像仓库,分为公有仓库和私有仓库。注意与注册服务器(Registry)的区别:注册服务器是存放仓库的地方,一般会有多个仓库;而仓库是存放镜像的地方,一般每个仓库存放一类镜像,每个镜像利用 tag 进行区分,比如 Ubuntu 仓库存放有多个版本(12.04、14.04等)的 Ubuntu 镜像。

目前最用的 Registry 是官方的 Docker Hub,这也是默认的 Registry,拥有大量的高质量的官方镜像 。除此以外,还有 Red Hat 的 Quay.io ;Google 的 Google Container RegistryKubernetes (K8s) 的镜像使用的就是这个服务;以及代码托管平台 GitHub 推出的 ghcr.io

三、Docker 安装

Docker 可以安装在 Windows、Linux、Mac 等各个平台上。具体可以查看文档 Install Docker

环境准备: Linux要求内核3.0以上

查询内核版本命令:

 uname -r

在这里插入图片描述
这里使用的OS是Ubuntu,可以看到 版本是符合要求的。

准备好环境之后,接下来按着官方文档来一步一步安装。
在这里插入图片描述
这里使用官方推荐的第一种方法安装。
在这里插入图片描述

第一步:卸载旧版本

 sudo apt-get remove docker docker-engine docker.io containerd runc

如果有的话就卸,没有则省略。

第二步:更新apt包索引和安装包,以允许apt使用HTTPS存储库:

 sudo apt-get update
 
 sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

第三步:添加Docker官方的GPG密钥

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

第四步:设置镜像的仓库

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

在这里插入图片描述
这里默认是从国外的,不推荐,推荐使用国内的。

echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]  http://mirrors.aliyun.com/docker-ce/linux/ubuntu\
   $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

第五步:更新apt包索引

sudo apt-get update

第六步:安装最新版本的Docker Engine和containerd

sudo apt-get install docker-ce docker-ce-cli containerd.io # docker-ce 社区版 而ee是企业版

🆗,至此安装完成!如果 Docker 没启动的话,先启动一下。

sudo systemctl start docker

第七步:使用docker version查看是否安装成功

sudo docker version

在这里插入图片描述
出现这个页面就是成功安装了!

第九步:测试 hello-world

sudo docker run hello-world

在这里插入图片描述
hello-world 第一次需要先下载。
在这里插入图片描述

最后:查看下载的镜像

docker images

在这里插入图片描述
🆗,都没什么问题!

补充(镜像加速,卸载docker):

1、卸载 Docker:

#1.卸载 Docker Engine、CLI 和 Containerd 包:
sudo apt-get purge docker-ce docker-ce-cli containerd.io

#2. 删除所有镜像、容器和卷 //主机上的映像、容器、卷或自定义配置文件不会自动删除。
sudo rm -rf /var/lib/docker # /var/lib/docker 是docker的默认工作路径!
sudo rm -rf /var/lib/containerd

2、阿里云镜像加速:

因为默认的 docker 仓库是国外的,所以这里把仓库改为aliyun的。
在这里插入图片描述
依次执行下面命令:

sudo mkdir -p /etc/docker

sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://j5l0vyp9.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload

sudo systemctl restart docker

四、Docker运行原理:

回顾 HelloWorld 流程:

在这里插入图片描述
run的流程图:
在这里插入图片描述

Docker镜像加载原理:

docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统 UnionFS(下载的时候看到一层层的下载就是这个) 。

UnionFs (联合文件系统):Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

分层理解:

在这里插入图片描述
为什么Docker镜像要采用这种分层的结构呢?

  • 最大的好处:资源共享,比如有多个镜像都从相同的 Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

例如:当系统中已经有了 CentOS 镜像,那么后面再有用到 CentOS 镜像的就不用再下载一次了。

查看镜像分层的方式可以通过docker image inspect 命令:
在这里插入图片描述

五、Docker的常用命令:

帮助命令:

docker version     #显示docker的版本信息。
docker info        #显示docker的系统信息,包括镜像和容器的数量
docker 命令 --help  #帮助命令

镜像命令:

docker images #查看所有本地主机上的镜像 可以使用 docker image ls代替
docker search #搜索镜像
docker pull   #下载镜像 = docker image pull
docker rmi    #删除镜像 = docker image rm

docker images 查看所有本地主机上的镜像:
在这里插入图片描述

#可选项
-a,--all    #列出所有镜像
-q,--quiet  #只显示镜像的id

docker search 搜索镜像
在这里插入图片描述

#可选项,通过收藏来过滤
-f/--filter=STARS=3000 #搜索出来的镜像就是STARS大于3000的

在这里插入图片描述

docker pull 下载镜像

#下载镜像 docker pull 镜像名
smk@ubuntu:~$ sudo docker pull mysql
Using default tag: latest #如果不写tag,默认就是latest
latest: Pulling from library/mysql 
33847f680f63: Pull complete #分层下载: docker image 的核心 联合文件系统
5cb67864e624: Pull complete 
1a2b594783f5: Pull complete 
b30e406dd925: Pull complete 
48901e306e4c: Pull complete 
603d2b7147fd: Pull complete 
802aa684c1c4: Pull complete 
715d3c143a06: Pull complete 
6978e1b7a511: Pull complete 
f0d78b0ac1be: Pull complete 
35a94d251ed1: Pull complete 
36f75719b1a9: Pull complete 
Digest: sha256:8b928a5117cf5c2238c7a09cd28c2e801ac98f91c3f8203a8938ae51f14700fd #签名 防伪
Status: Downloaded newer image for mysql:latest 
docker.io/library/mysql:latest #真实地址

#二者等价
docker pull mysql
docker pull docker.io/library/mysql:latest

指定版本下载:
在这里插入图片描述
在这里插入图片描述

docker rmi 删除镜像

docker rmi -f 镜像id #删除指定的镜像
docker rmi -f 镜像id 镜像id 镜像id 镜像id #删除指定的镜像
docker rmi -f $(docker images -aq) #删除全部的镜像

在这里插入图片描述
注意这里不是root用户,需要加 sudo

容器命令:

docker run 镜像id     #新建容器并启动
docker ps            #列出所有运行的容器 
docker rm 容器id      #删除指定容器
docker start 容器id   #启动容器
docker restart 容器id #重启容器
docker stop 容器id    #停止当前正在运行的容器
docker kill 容器id    #强制停止当前容器

有了镜像才可以创建容器;先下载一个 centos 镜像来测试:

docker pull centos
1.新建容器并启动(注意和 start 的区别,start 只能启动):
docker run [可选参数] 镜像名 

#参数说明
--name="Name" 容器名字 tomcat01 tomcat02 用来区分容器
--rm 容器停止后自动删除容器
-d 后台方式运行(不产生输出到Shell)
-it 使用交互方式运行(就是进入容器内)
-p 指定容器的端口 -p 8080(宿主机):8080(容器)
     #一共有四种用法:
	-p ip:主机端口:容器端口
	-p 主机端口:容器端口(常用)
	-p 容器端口
	容器端口
-P(大写) 随机指定端口

启动并进入容器:
在这里插入图片描述
/bin/bash:即启动 bash类型的shell。

退出容器:

exit       #容器停止并退出
ctrl +P +Q #容器不停止退出
2.列出所有运行的容器:

在这里插入图片描述

docker ps [可选参数] #列出当前正在运行的容器
#参数说明
-a #列出当前正在运行的容器 + 带出历史运行过的容器
-n=? #显示最近创建的容器
-q #只显示容器的编号

在这里插入图片描述

3.启动和停止容器:
docker start 容器id   #启动容器
docker restart 容器id #重启容器
docker stop 容器id    #停止当前正在运行的容器
docker kill 容器id    #强制停止当前容器

在这里插入图片描述

4.删除容器:
docker rm 容器id # 删除指定的容器,不能删除正在运行的容器,
要删除正在运行中的容器,需要使用 -f 选项

docker rm -f $(docker ps -aq) # 强制删除所有的容器
docker ps -a -q|xargs docker rm # 删除所有的容器

在这里插入图片描述

5.查看容器中进程信息:
docker top 容器id

在这里插入图片描述
注:必须是运行的容器。

6.进入当前正在运行的容器:

我们通常容器都是使用后台方式运行的,需要进入容器,修改一些配置。命令:

docker exec -it 容器id bashshell

在这里插入图片描述

# 方式二
docker attach 容器id

在这里插入图片描述

#区别
docker exec #进入当前容器后开启一个新的终端,可以在里面操作。(常用)
docker attach # 进入容器正在执行的终端
7.文件从主机拷贝到容器:

如果需要将自己的Web项目(页面)部署到Nginx上,可以使用容器拷贝命令将指定路径下所有的文件和文件夹拷贝到容器的指定目录中。

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

如果不愿意拷贝文件也可以在创建容器时通过数据卷操作--volume将指定的文件夹映射到容器的某个目录中,例如将Web项目的文件夹直接映射到/usr/share/nginx/html目录。我们先通过下面的命令让刚才创建的容器停止运行。

docker stop mynginx

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

docker run -d -p 80:80 --name mynginx --volume /root/docker
8.文件从容器内拷贝到主机上:
docker cp 容器id:容器内路径 主机目的路径

例:
在这里插入图片描述

Docker可视化:

portainer 是 docker 图形化界面管理工具!提供一个后台面板供我们操作!(不建议使用)

#官网查找安装命令
docker run -d -p 8000:8000 -p 9000:9000 --name=portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce

访问:
在这里插入图片描述
进来之后就是这样。
在这里插入图片描述
可以看到一些本地docker的配置
在这里插入图片描述

六、构建镜像:

通过上面的讲解,我们已经掌握了如何通过官方提供的镜像来创建容器。当然如果愿意,我们也可以用配置好的容器来生成镜像。简而言之,docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部,这一层就是我们通常说的容器层,容器之下的都叫镜像层。

在这里插入图片描述
之前我们讲过了如何查找、列出镜像和拉取(下载)镜像,接下来看看构建镜像的两种方式:

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

使用commit命令构建镜像

命令:

docker commit [-m="描述信息" -a="作者"] 容器id 目标镜像名:[TAG]

为了演示如何构建镜像,我们先使用Ubuntu镜像来定制一个容器,命令如下所示。

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

在容器中执行下面的命令来安装Apache服务器并退出容器。

apt -y upgrade
apt -y install apache2
exit

我们将这个容器作为一个定制的Web服务器保存起来,当需要这样一台Web服务器的时候,就没有必要重新创建容器并安装Apache了。

首先我们通过下面的命令查看容器的ID。

docker ps -a
docker ps -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 CORS

app = 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
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

在这里插入图片描述

Dockerfile指令

想了解Dockerfile的指令可以查看官方提供的参考手册,下面我们为大家介绍一些常用的指令。

  1. FROM:设置基础镜像,必须是Dockerfile中的第一条指令。
FROM <镜像名> [AS <别名>]

FROM <镜像名>[:<标签>] [AS <别名>]
  1. RUN:指定构建镜像时要执行的命令。
RUN <命令> [参数1], [参数2], ... 

RUN ["可执行文件", "参数1", "参数2", ...]
  1. CMD:指定构建镜像后要执行的命令。
CMD <命令> [参数1], [参数2], ...

CMD ["可执行文件", "参数1", "参数2", ...]

说明:Docker不同于虚拟机,容器本身就是一个进程,容器中的应用应该位于前台运行。CMD命令相当于就是用来指定容器主进程(创建容器后要在前台执行的程序)的,如果主进程结束了,容器也就停止运行了。所以在容器中启动Nginx不能使用service nginx start或是systemctl start nginx而是要通过CMD ["nginx", "-g", "daemon off;"]让它在前台运行。

  1. ENTRYPOINT:和CMD类似,也可以执行命令,但docker run命令行中指定的任何参数都会被当做参数再次传给ENTRYPOINT指令中的命令,这就使得我们可以构建一个镜像,它既可以运行一个默认的命令,也支持通过docker run命令行为该命令指定可覆盖的参数选项。
ENTRYPOINT <命令> [参数1], [参数2], ...

ENTRYPOINT ["可执行文件", "参数1", "参数2", ...]
  1. WORKDIR:在通过镜像创建新容器时,在容器内部创建一个工作目录,ENTRYPOINT和CMD指定的程序会在这个目录下执行。在使用docker run命令时可以通过-w参数来覆盖由WORKDIR指定的工作目录。例如:
WORKDIR /opt/webapp
docker run -w /usr/share/webapp ...
  1. ENV:在创建镜像时设置环境变量。在使用docker run命令时,可以通过-e参数来修改环境变量的设置。例如:
ENV DEFAULT_PORT=8080
docker run -e "DEFAULT_PORT=8000" ...
  1. USER:指定镜像会以什么用户身份去运行。例如:
USER nginx
  1. VOLUME:在创建容器时添加一个数据卷的挂载点。通过数据卷操作可以实现容器间数据的共享和重用,对卷所作的修改可以马上生效而不需要重新启动容器,我们之前创建容器时使用--volume参数就是为了实现数据卷的映射操作。
VOLUME ["/路径1", "/路径2/子路径2.1/", ...]
  1. ADD:将构建目录下的文件和文件夹复制到镜像中,如果是压缩文件和归档文件,ADD命令会对这些文件进行解压缩解归档的操作。
ADD [--chown=<用户>:<用户组>] <源文件> <目标文件>
  1. COPY:非常类似于ADD,但不会主动对文件进行提取操作。

  2. LABEL:为Docker镜像添加一些元数据,在使用docker inspect命令时会看到这些元数据。

LABEL version="1.0.0" location="Chengdu"
  1. ONBUILD:为镜像添加触发器,当一个镜像被用作其他镜像的基础镜像,触发器将会被执行。例如:
ONBUILD ADD . /app/src
ONBUILD RUN cd /app/src && make

七、多容器管理

Docker Compose

可以通过安装Docker Compose工具来实现基于YAML文件的容器编排,YAML文件会定义一系列的容器以及容器运行时的属性,Docker Compose会根据这些配置来管理容器。

  1. 安装Docker Compose(新版默认安装)
curl -L "https://github.com/docker/compose/releases/download/1.25.4/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
  1. 使用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, loads

from flask import Flask
from flask_restful import Resource, Api
from flask_cors import CORS
from redis import Redis

app = 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: ./myapp
    ports:
      - '8000:8000'
    links:
      - redis-master
  web-server:
    image: nginx
    ports:
      - '80:80'
    volumes:
      - ./html:/usr/share/nginx/html
  redis-master:
    image: redis
    expose:
      - '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(K8S)

实际的生产环境中常常需要部署和管理多个协同工作的容器,docker compose解决了多容器创建和管理的问题,但是实际项目中,我们还需要Kubernetes(以下都简称为K8S)来提供一个跨主机集群的容器调度平台。K8S可以进行自动化容器的部署、扩展和操作,从而提供以容器为中心的基础架构。该项目是谷歌在2014年启动的项目,建立在谷歌公司十余年运维经验的基础之上,而且谷歌自己的应用也是运行在容器上的。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐