Docker容器化部署及应用实战

一、认识docker

        Docker是为开发人员和系统管理员提供容器构建,运行和共享应用程序的平台。使用容器来部署应用程序称为容器化。容器不是新的,但用于轻松部署应用程序的容器却是新的。

二、docker的优势

  • (1)有助于Microservices的落地和部署
  • (2)充分利用物理机资源,同时能够整合服务器资源
  • (3)提高开发效率,测试效率,部署效率,有利于DevOps的落地,CICD
  • (4)云原生落地,应用更好地迁移

三、docker的安装

3.1 Docker依赖于系统的一些必要工具:

yum install -y yum-utils device-mapper-persistent-data lvm2

Device Mapper 是 Linux2.6 内核中支持逻辑卷管理的通用设备映射机制,而device-mapper-persistent-data和lvm2是Device Mapper存储驱动程序必须要的工具:

  • device-mapper-persistent-data : 存储驱动管理
  • lvm2: 逻辑卷管理

3.2  设置Docker安装的yum源

yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

 3.3 安装Docker

yum clean all
yum makecache fast # 更新 yum 缓存
yum -y install docker-ce # 安装docker-ce

3.4 启动Docker

systemctl start docker

3.5 设置开机启动

systemctl start docker.service
systemctl enable docker.service

四、运行第一个容器

接下来,我们通过Docker部署一个Tomcat容器。

4.1 创建tomcat容器

docker pull tomcat
docker run -d --name first_tomcat -p 8080:8080 tomcat

  •  -d 表示后台运行容器,并返回容器ID
  • -p 将容器的端口映射到宿主机的端口,第一个8080表示映射到宿主机的端口,第二个8080表示tomcat容器的端口,相当于把容器中运行的tomcat的端口号映射到宿主机的8080端口上

4.2 进入到容器中

docker exec -it containerid /bin/bash

 4.3 相关命令

  • 查看容器列表: docker contailer ls
  • 进入到容器:docker exec -i containerid /bin/bash
  • 在容器中安装软件:apt-get update apt-get install vim
  • 查看所有容器:docker ps -all

4.4 访问tomcat

        运行tomcat容器之后,访问 http://192.168.216.129:8080 , 这个时候会提示400,找不到页面。

        原因是用阿里云仓库中提供的tomcat镜像,默认的webapps的名字变成了webapps.dist,导致没有默认可以访问的页面,所以我们只需要进入到容器中修改一下就行。

  • docker exec -i containerid /bin/bash
  • 删除webapps目录,再执行 mv webapps.dist webapps 。重新访问就可以进入到tomcat的首页了

五、 Docker pull比较慢

        在上面的案例中,执行 docker pull 去远程仓库拉去镜像时,会发现很慢,这是因为docker默认从hub.docker.com官方库中拉去镜像,这个是国外的网站访问起来比较慢,所以我们可以通过以下步骤将镜像源修改为阿里云:

1.登录阿里云,找到 产品与服务 -> 容器镜像服务 -> 镜像加速器 ,可以看到下图所示的aliyun镜像加速器地址。

2.执行 vim /etc/docker/daemon.json 下面命令,创建/修改文件,并设置加速器地址。 

daemon.json: 

{
"registry-mirrors": ["https://089rhvhq.mirror.aliyuncs.com"]

sudo systemctl daemon-reload
sudo systemctl restart docker

3.再次执行 docker pull tomcat , 就会发现下载速度快了很多

六、Docker的整体架构

  • Docker client和Docker daemon(守护进程)进行交互。Docker daemon负责对docker container的创建,运行,构造和分发等操作
  • Docker client和Docker daemon可以运行在同一系统上,或者可以使用docker client连接远程的docker daemon
  • Docker client和Docker daemon使用REST API通信,通过UNIX套接字或网络接口进行通信

Docker容器化部署及应用实战_第1张图片

七、什么是容器和镜像

        容器:是打包代码以及所有相关依赖项的软件标准单元,它可以使得应用从一个计算机环境快速可靠的移动到另外一个计算机环境去运行。

        Docker:容器镜像是一个轻巧的、独立的、可执行的软件包,它包含了运行应用程序所需要的一切要素,如:代码、运行环境、系统工具、系统库以及环境。

        容器和镜像的关系:简单来说可以这样去理解:一个软件包通过docker 构建之后成为一个image,而这个image在Docker Engine上运行时就变成了容器。每个容器都是相互隔离的,我们可以简单的把容器看作是一个建议版的Linux运行环境,Docker就是利用容器来运行应用的。

八、镜像的构成

        docker的镜像实际上是由一层一层的文件系统组成,这种层级的文件系统叫UnionFS(联合文件系统)。它是一种分层、轻量级并且高性能的文件系统,它支持文件系统的修改作为一次提交来一层一层的叠加。

        前面官方资料讲过,Docker容器镜像包含了运行该应用程序所需要的一切因素,如代码、运行环境、系统工具、系统库,它的组成形态如下图所示:

需要注意的是,这些层都是只读,无法编辑。

Docker容器化部署及应用实战_第2张图片

其中,操作系统就是一个基础镜像,所谓的基础镜像就是没有父级镜像。

8.1 UnionFS(联合文件系统)简介

Linux得操作系统组成:内核空间、用户空间。

bootfs(不同的linux发行版本,bootfs基本上是一致的)

rootfs(不同的发行版本,用户空间的文件系统是不一样的)/dev /bin /etc /tmp

  • bootfs可以复用,每一个不同的发行版本对应的镜像,只需要提供不同的rootfs就行 
  • 精简的os,centos(200m)

8.2 镜像分层的demo演示

接下来,为了更好的说明镜像分层结构,我写一个Demo给大家看一下:

1.创建一个Dockerfile

## 指明当前要构建的镜像所继承的基础镜像
FROM java:8
## 设置工作目录
WORKDIR /app
## 把Hello.java拷贝到工作目录
COPY Hello.java /app
## docker镜像编译时出发的动作,它会在当前镜像上执行指定命令并形成一个新的层
RUN ["javac","Hello.java"]
## docker run执行时,会执行这个命令
ENTRYPOINT ["java","Hello"]

2.编写一个Hello.java,其中while循环是为了让容器不结束

public class Hello{
    public static void main(String[] args){
        System.out.println("Hello GupaoEdu.com");
        while(true){
        }
    }
}

3.执行 docker build -t gupaoedu:hello-image . 具体的语法为 docker build [options] PATH|URL

  • -t 表示设置镜像的名字以及标签,一般是name:tag
  • . 表示dockerfile的路径
  • 构建成功之后,通过 docker images 就可以看到创建好的镜像
  • docker run gupaoedu:hello-image 运行这个
  • 运行之后由于设置了死循环,所以我们可以通过 docker exec -it containerId /bin/bash 进入到容器层。

 8.3 构建过程

首先FROM java:8表示当前镜像使用的基础镜像层,

然后执行RUN,执行RUN命令都是新建一个层,这一层用来编译Hello.java,而由于前面设置了WORKDIR,所以在构建镜像的每一层都会存在这个工作目录。

最终通过docker run运行,那么在镜像最上层会增加一个容器层,我们可以通过容器层来访问镜像。

Docker容器化部署及应用实战_第3张图片

九、可以写的容器

        这时可能就有人会问了:如果多个容器共享一份基础镜像,当某个容器修改了基础镜像的内容,比如/etc 下的文件,这时其他容器的 /etc 是否也会被修改?答案是不会!

        原因是对于镜像来说,它是只读的,也就是你无法去修改镜像。
        那有同学又有疑问了,老师,你前面安装tomcat的时候,不是修改了tomcat这个镜像里面webapp目录吗?
        实际上,容器的本质是镜像在运行的时候,在镜像最上层添加了一个可写层,我们所有的修改都是在这一层来完成的,而这个修改并不会对基础镜像产生影响,修改容器中的数据实际上是先从镜像层把数据复制到容器层,然后修改之后会把修改之后的数据保存在容器层,镜像层不会发生变化,这个其实就是UnionFS(联合文件系统)来实现的,所以它的影响只局限在当前的容器中。

UnionFS的一个最主要的应用是,把一张CD/DVD和一个硬盘目录给联合 mount在一起,然后,你就可以对这个只读的CD/DVD上的文件进行修改(当然,修改的文件存于硬盘上的目录里)。

Docker容器化部署及应用实战_第4张图片

        所有对容器的改动,无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

下面我们深入讨论容器层的细节:
        镜像层数量可能会很多,所有镜像层会联合在一起组成一个统一的文件系统。如果不同层中有一个相同路径的文件,比如 /a,上层的 /a 会覆盖下层的 /a,也就是说用户只能访问到上层中的文件 /a。在容器层中,用户看到的是一个叠加之后的文件系统。

  1. 添加文件:在容器中创建文件时,新文件被添加到容器层中。
  2. 读取文件:在容器中读取某个文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后打开并读入内存。
  3. 修改文件:在容器中修改已存在的文件时,Docker 会从上往下依次在各镜像层中查找此文件。一旦找到,立即将其复制到容器层,然后修改之。
  4. 删除文件:在容器中删除文件时,Docker 也是从上往下依次在镜像层中查找此文件。找到后,会在容器层中记录下此删除操作。

十、Dockerfile

10.1 把springboot项目构建成image

1.在spring-cloud-eureka-server项目的Dockerfile示例:

FROM openjdk:8
MAINTAINER [email protected]
LABEL name="gper-mall-eureka-server" version="1.0" author="Mic"
WORKDIR /gper/base
EXPOSE 9090
ADD ./spring-cloud-eureka-server-0.0.1-SNAPSHOT.jar ./gper-mall-eureka-server.jar
ENTRYPOINT ["java","-jar","gper-mall-eureka-server.jar"]

2.前提:程序不可运行,需要再pom里添加如下配置:

Docker容器化部署及应用实战_第5张图片

3.然后maven-package打包

4.复制Dockerfile文件和jar包到/data/docker/app文件夹

Docker容器化部署及应用实战_第6张图片

4.在 /data/docker/app中执行命令,生成镜像:

docker build -t gpermall:eureka-server .

Docker容器化部署及应用实战_第7张图片

5.查看打包出来的images:

docker images

Docker容器化部署及应用实战_第8张图片

6.运行docker

docker run --name eureka-server-9090 -p 9090:9090 gpermall:eureka-server

Docker容器化部署及应用实战_第9张图片

10.2 FROM

指定当前镜像的基础镜像,也就是当前新的镜像是在指定的基础镜像之上运行。

FROM ubuntu:14.04

10.3 RUN

在docker build期间执行命令,在build过程中,每一个RUN命令都会新建一个镜像层

shell:RUN <命令行命令> #与终端shell命令一样exec:RUNR ["可执行文件","参数1","参数2"]

RUN groupadd -r mysql && useradd -r -g mysql mysql

10.4 ENV

设置环境变量,可以通过${key}来引用,并且还可以通过 docker run --e key=value来设置环境变量的值.

10.5 COPY/ADD

将主机的文件复制到镜像内,如果目录不存在,会自动创建所需要的目录,注意只是复制,不会提取和解压。

ADD和COPY的作用类似,只是ADD会对压缩文件进行自动解压

10.6 WORKDIR

指定镜像的工作目录,之后的命令都是基于此目录工作,若不存在则创建

10.7 CMD

容器启动的时候默认会执行的命令,若有多个CMD命令,则最后一个生效。

CMD ["mysqld"]
或 
CMD mysqld

10.8 ENTRYPOINT

        功能和CMD类似,但是和CMD不同的是,docker run执行的时候,可以在命令行参数中指定要运行的程序来覆盖Dockerfile中运行的指令。

        而ENTRYPOINT不同,它无法通过docker run的命令行参数来覆盖ENTRYPOINT需要执行的指令,而且命令行中声明的数据会被当做参数传递给ENTRYPOINT指令指定的程序。

        他们的相同点都是在docker运行的时候会默认触发执行的命令。

10.9 EXPOSE

指定镜像要暴露的端口,启动镜像时,可以使用-p将该端口映射给宿主机。

EXPOSE 3306

十一、Volume(数据卷)

Docker容器化部署及应用实战_第10张图片

Docker容器化部署及应用实战_第11张图片

拓展:

Docker学习笔记(6)——Docker Volume - 简书

你必须知道的Docker数据卷(Volume) - EdisonZhou - 博客园

docker volume - 简书

你可能感兴趣的:(docker,容器,运维)