一、Dokcer简介

官方介绍:

​         Docker 是一个开源的应用容器引擎,基于Go 语言并遵从 Apache2.0 协议开源。

​         Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。

​         容器是完全使用沙箱机制,相互之间不会有任何接口(类似 iPhone 的 app),更重要的是容器性能开销极低。

​         Docker的构想是要实现“Build, Ship and Run Any App, Anywhere”,即通过对应用的封装(Packaging)、分发(Distribution)、部署(Deployment)、运行生命周期(Runtime)进行管理,达到应用组件级别的“一次封装,到处运行”。

本人理解:

​         我们在开发到上线一个程序的时候需要接触很多环境,比如:开发环境(一般是在自己电脑)、测试环境、生产环境,在不同的环境中我们开发出的程序可能出现一些问题。可能在自己电脑上可以跑的程序,到了其它机器上就会因为环境不同而出现一些问题。而且换到不同的机器上我们就需要重新配置环境。例如下图所示。所以我们就想,如果能把环境一起打包运行,那样不就可以解决不同运行环境的问题了。使用Docker就可以解决这样的问题,我们可以使用Docker将程序以及环境打包为一个镜像,并上传到远程仓库,当需要在其它机器上运行时,只需要将镜像从远程仓库拉取下来直接运行即可。

在这里插入图片描述

​         Docker是一个C/S架构的软件,Docker会启动一个守护进程用来接收客户端的命令并执行相应的命令。比如:docker run 镜像名,可以根据一个镜像运行一个容器。

1、Docker中的名词概念

镜像(Image):

​         Docker中的镜像就像是一个只读的模板,比如操作系统镜像,我们可以使用操作系统镜像来安装一个操作系统;又像是面向对象中的类,通过类我们可以创建一个对象。镜像是可以复用的,我们可以通过Docker运行一个镜像实例,运行起来的镜像就是一个容器。

容器(Container):

​         Docker容器类似一个轻量级的沙箱,Docker利用容器技术来运行和隔离应用。容器是从镜像创建的应用运行实例。它可以启动、开始、停止、删除,而这些容器都是彼此相互隔离、互不可见的。

​         可以把容器看作一个简易版的Linux系统环境(包括root用户权限、进程空间、用户空间和网络等)以及运行在其中的应用程序打包而成的盒子。

仓库(Repository)

​         Docker仓库类似代码仓库,是Docker集中存放镜像文件的仓库,仓库分为私有仓库和公有仓库。可以通过Docker从仓库中拉取一个镜像,也可以上传自己的镜像。目前最大的公开仓库是官方提供的Docker Hub,就像Github一样,Docker Hub存放了很多官方的或者非官方的镜像,例如:nginx镜像、redis镜像等。官网:https://hub.docker.com/

        如下图,下图中包含了三部分,分别时Docker客户端、Docker守护进程以及远程仓库。Docker客户端可以接收命令并通知Docker守护进程来进行一系列的操作,比如拉取镜像、运行容器等。Docker守护进程将会管理镜像以及容器。远程仓库存放了很多种不同的镜像。

在这里插入图片描述

Docker的安装:Ubuntu20.04安装Docker_Peerless__的博客-CSDN博客

二、Docker基本使用

在使用下面的命令时,可以加参数 --help 来查看帮助文档。例如dokcer run --help:

下面显示了docker run命令的使用方式以及其它的可选参数和其解释。

在这里插入图片描述

1、镜像

1.1 查看镜像
docker images 

在这里插入图片描述

使用docker images命令可以查看本机已经存在的镜像。分别显示了镜像名、标签(版本信息)、镜像ID、创建时间以及镜像的大小。

除此之外,还有一些可选参数,可以通过docker images --help 命令来查看,下面两个是比较常用的参数:

# -a参数,显示所有的镜像 docker images -a
-a, --all             Show all images (default hides intermediate images)
# -q参数,只显示镜像ID
-q, --quiet           Only show image IDs
1.2 给镜像设置标签
docker tag sourname:tag  desname:tag
#例如:
docker tag ubuntu:18.04 myubuntu:lastest
1.3 搜索镜像
docker search 镜像名

#参数:
# 过滤输出内容
  -f, --filter filter   Filter output based on conditions provided
# 限制输出个数
  --limit int       Max number of search results (default 25)
  
# 例如
docker search --filter=is-official=true mysql           # 搜索mysql官方镜像 
docker search --filter=stars=200 mysql                  # 搜索star大于200的mysql镜像
docker search --limit 5 mysql                           # 只显示5个输出

在这里插入图片描述

使用docker search可以从远程仓库搜索镜像,上面显示了镜像名、描述、stars、是否是官方镜像等信息。

1.4 拉取镜像
docker pull 镜像名
docker pull 镜像名:tag

#例如 
docker pull mysql             # 不加tag,将会拉取最新版本
docker pull mysql:5.7         # 拉取5.7版本的mysql

在镜像名后可以指定拉取的版本,如果不指定就会拉取最新版本,关于镜像的版本可以到docker hup来搜索。网址:https://hub.docker.com/

在这里插入图片描述

1.5 删除镜像

使用下面命令可以删除本机仓库中的一个镜像,rmi ==> remove image

docker rmi 镜像名 或 镜像ID

#例如 docker rmi centos   或 docker rmi 9f266d35e02c , 命令Docker images可以查看镜像ID

参数:
# 强制删除,类似linux命令 rm -f 
-f, --force      Force removal of the image

# 如果要删除所有的镜像可以使用以下命令, docker images -aq 会显示所有镜像的ID
docker rmi `docker images -aq`docker rmi $(docker images -aq)
1.6 导出和载入镜像

Docker镜像的save和load命令可以将镜像导出到本地以及加载本地镜像到镜像库。使用save命令可以将镜像导出到本地,这样就可以跟别人分享自己的镜像,当然也可以提交到远程仓库,将在后面介绍。通过load命令则可以加载别人分享的镜像。

docker save -o 生成的镜像名 镜像
# 例如
docker save -o mysql5_7.tar mysql:5.7
docker load -i 本地镜像名  或者
docker load < 本地镜像名

2、容器

2.1 运行容器
docker run 镜像名

参数:
  -d, --detach               Run container in background and print container ID  后台运行容器
  -e, --env list             Set environment variables                           设置环境变量
  --expose list              Expose a port or a range of ports                   暴露端口
  -i, --interactive          Keep STDIN open even if not attached                交互模式
  --name string              Assign a name to the container                      给当前运行的容器指定名字
  -p, --publish list         Publish a container's port(s) to the host           指定端口映射
  -P, --publish-all          Publish all exposed ports to random ports           随机指定暴露的端口映射
  -t, --tty                  Allocate a pseudo-TTY                               分配一个终端
  -v, --volume list          Bind mount a volume                                 挂载数据卷
  --volumes-from list        Mount volumes from the specified container(s)       从一个数据卷容器挂载目录
  -w, --workdir string       Working directory inside the container              指定容器中的工作目录

我们可以使用交互模式来运行一个容器,例如下面命令:

docker run -it --name c1 centos /bin/bash

在这里插入图片描述

-t选项让Docker分配一个伪终端并绑定到容器的标准输入上,-i则让容器的标准输入保持打开,–name给容器指定名字,centos为创建容器使用的镜像,/bin/bash为容器中运行的终端。如果镜像不存在,Docker会从远程仓库拉取,然后再运行。如下图,运行容器后发现终端发生了变化,说明我们已经进入了容器,用户为root用户,@后的一串字符为当前容器的ID。可以使用ls命令来查看当前目录下的文件。

在这里插入图片描述

输入exit命令可以退出当前容器。

使用docker ps -a来查看所有容器,发现刚刚运行的容器在退出后就停止运行了。对于所创建的bash容器,当用户使用exit命令退出bash进程后,容器也会自动退出。这是因为对于容器来说,当其中的应用退出后,容器的使命完成,也就没有运行的必要了。

在这里插入图片描述

使用 Ctrl + p + q来退出容器可以让容器在后台继续运行。

我们可以在启动时让容器在后台运行,这样在退出容器后,容器会继续运行。

docker run -id --name c2 centos 

在这里插入图片描述

运行后,输出了运行的容器的ID。使用docker ps -a命令来查看所有容器,发现刚刚启动的容器还在运行

可以使用下面的命令进入容器:

docker exec -it c2 /bin/bash 或
docker exec -it 29f35e8928c5 /bin/bash

在这里插入图片描述

在进入容器并退出后发现,c2容器依然在运行。

当利用docker run来创建并启动容器时,docker在后台运行的标准操作包括:

  • 检查本地是否存在指定的镜像,不存在就从远程仓库下载;
  • 利用镜像创建一个容器,并启动该容器;
  • 分配一个文件系统给容器,并在只读的镜像层外面挂载一层可读写层;
  • 从宿主主机配置的网桥接口中桥接一个虚拟接口到容器中去;
  • 从网桥的地址池配置一个IP地址给容器;
  • 执行用户指定的应用程序;
  • 执行完毕后容器被自动终止。
2.2 查看容器
docker ps

参数:
# 查看所有容器
  -a, --all             Show all containers (default shows just running)
# 只显示容器ID
  -q, --quiet           Only display container IDs

使用docker ps可以查看容器,类似linux的ps命令查看进程。不加参数只会显示当前正在运行的容器,-a参数可以显示所有容器,-q只显示容器ID,如果要删除所有容器就可以使用该参数了,类似删除全部镜像。

2.3 停止容器

1)暂停容器

# 暂停容器
docker pause 容器名 或 ID
# 继续运行暂停的容器
docker unpause 容器名 或 ID

2)终止容器

docker stop 容器名 或 ID

在这里插入图片描述

该命令会首先向容器发送SIGTERM信号,等待一段超时时间后(默认为10s),再发送SIGKILL信号来终止容器。

2.4 启动容器
docker start 容器名 或 ID

在这里插入图片描述

# 重启容器,先终止再启动
docker restart 容器名 或 ID
2.5 删除容器
docker rm 容器名 或 ID

参数:
#强制删除容器
  -f, --force     Force the removal of a running container (uses SIGKILL)

容器在运行时使用docker rm无法删除,需要加-f参数才可。

如果要删除所有容器,也可以使用类似删除所有镜像的命令:

docker rm `docker ps -aq`docker rm $(docker ps -aq)
2.6 导入和导出容器

某些时候,需要将容器从一个系统迁移到另外一个系统,此时可以使用Docker的导入和导出功能。

1)导出容器

导出容器是指,导出一个已经创建的容器到另一个文件,不管这个容器是否处于运行状态。

docker export -o exportname 容器名   或
docker export 容器名 > exportname

# 例如
docker export -o test_for_run.tar ce1
docker export ce1 > test_for_run

之后,可将导出的tar文件传输到其它机器上,然后通过导入命令导入到系统中,实现容器的迁移。

2)导入容器

docker import filename 
2.7 查看容器的相关信息

使用docker inspect可以查看容器的具体信息,会以json格式返回容器ID、创建时间、路径、状态、镜像、配置在内的各项信息。

docker inspect 容器名 或 ID
# 同样使用docker inspect 镜像名 或 镜像ID 也可以查看镜像的相关信息

在这里插入图片描述

里面有很多参数,在这里只展示了一部分。

使用下面的命令可以查看docker容器中的进程信息。

docker top 容器名 或 ID
2.8 运行容器时的其它参数
设置环境变量
-e, --env list             Set environment variables       设置环境变量

使用-e命令可以给运行的容器设置环境变量

在这里插入图片描述

暴露端口
--expose list              Expose a port or a range of ports                   暴露端口

例如,运行nginx时可以将容器的80端口进行暴露。

端口映射

我们在外部机器是无法直接通过网络与容器进行通信的,但是宿主机是可以和容器直接通信的,因此我们可以借助宿主机来和容器进行通信。

例如下图,在容器中运行了一个端口为3306的mysql数据库,在外部机器中是无法直接访问容器中的mysql的。因此可以配置一个端口映射,容器中的3306端口映射到宿主机的3307端口(也可以是其它端口),这样我们可以直接通过宿主机的IP以及端口来访问容器中的数据库。

在这里插入图片描述

  -p, --publish list         Publish a container's port(s) to the host           指定端口映射
  -P, --publish-all          Publish all exposed ports to random ports           随机指定暴露的端口映射

例如在运行nginx时,可以将容器内的80端口映射为宿主机的8080端口,我们就可以在浏览器中通过8080端口来访问容器中的nginx。-p自己指定映射的端口。

在这里插入图片描述

在这里插入图片描述

-P让docker来随机指定映射的端口。

在这里插入图片描述

在这里插入图片描述

可以使用docker inspect来查看映射的端口:

在这里插入图片描述

指定工作目录
-w, --workdir string       Working directory inside the container              指定容器中的工作目录

在这里插入图片描述

可以通过-w命令来指定容器中的工作目录,运行容器后,容器就在指定的工作目录。

2.9 数据管理

在生产环境中使用Docker,往往需要对数据进行持久化,或者需要在多个容器直接进行数据共享,这必然涉及容器的数据管理操作,容器中的管理数据主要有两种方式:

  • 数据卷(Data Volumes):容器内数据直接映射到本地主机环境;
  • 数据卷容器(Data Volume Containers):使用特定容器维护数据卷。
挂载数据卷

数据卷是一个可供容器使用的特殊目录,它将主机操作系统目录直接映射进容器,类似Linux中的mount行为。

数据卷可以提供很多有用的特性:

  • 数据卷可以在容器间共享和重用,容器间传递数据将变得高效与方便;
  • 对数据卷内数据的修改会立马生效,无论是容器内操作还是本地操作;
  • 对数据卷的更新不会影响镜像,解耦开应用和数据;
  • 卷会一直存在,直到没有容器使用,可以安全地卸载它(即使容器被删除了,本地数据卷也不会被删除)。
  -v, --volume list          Bind mount a volume                                 挂载数据卷
  # 使用:   -v 宿主机目录:容器目录

当容器在删除后,容器中的数据也就随之被删除了。如果我们运行了一个mysql的容器,当容器被删除后,我们不希望mysql中的数据也被删除。因此我们可以将容器中的数据与宿主机的一个目录建立一个映射,这两个目录中的数据会被同步。

在这里插入图片描述

如上图所示,运行了一个名字为c6的centos的容器,并指定了宿主机的/home/mgh/data与容器/usr/local/data的映射(如果路径中的文件夹不存在,则会创建),在容器的/usr/local/data目录中创建了hello.txt并写入内容。然后退出容器,在宿主机的/home/mgh/data目录中发现也有这样一个文件。同时在宿主机中创建了world.txt文件,进入容器后也可以看到该文件。

我们也可以将多个容器中的一个目录挂载在宿主机的同一个目录下,这样就可以在容器间共享数据了。

在这里插入图片描述

数据卷容器

多个容器共享数据,我们可以将它们挂载在同一个目录,如果创建比较多的容器的话,这种方式操作还是比较麻烦的。另一种方法就是创建一个数据卷容器,在运行这个容器时将目录挂载在宿主机上,在启动其它容器时我们可以使用–volumes-from并指定数据卷容器来共享数据。

  --volumes-from list              Mount volumes from the specified container(s)  从一个特殊的容器中挂载数据卷
  # 例如 也可以指定多个目录
  docker run -id --name volume-container -v /home/data:/usr/local/data centos
  docker run -id --name volume-des1 --volumes-from volume-container centos

在这里插入图片描述

如上图所示,先使用命令创建了一个数据卷容器,将容器中/usr/local/data挂载到宿主机的/home/data中,然后创建了三个容器并指定了数据卷容器。可以看到在数据卷容器的/usr/local/data目录下创建文件,其它几个容器都是可以共享数据的。

如果删除了挂载地容器,数据卷并不会被自动删除。如果要删除一个数据卷,必须在删除最后一个还挂载它的容器时显式使用docker rm -v命令来指定同时删除关联地容器。

三、应用部署

1、部署mysql

步骤如下:

  1. 搜索mysql镜像

     docker search mysql
    
  2. 拉取mysql镜像

    docker pull mysql:5.7
    
  3. 运行容器设置端口映射

    # 创建mysql目录用于存储mysql数据
    mkdir ~/mysql
    cd ~/mysql
    
    docker run -id \
    -p 3307:3306  \
    --name c_mysql  \
    -v ~/mysql/conf:/etc/mysql/conf.d  \
    -v ~/mysql/logs:/logs  \
    -v ~/mysql/data:/var/lib/mysql  \
    -e MYSQL_ROOT_PASSWORD=123456  \
    mysql:5.7
    

    参数说明:

    -p 3307:3306 将容器的3306端口映射到宿主机的3307端口。

    -v 挂载目录

    -e MYSQL_ROOT_PASSWORD=123456 初始化root密码

运行容器后,可以进入容器使用mysql客户端连接mysql查看。

docker exec -it 容器ID /bin/bash
mysql -uroot -p

在这里插入图片描述

也可以使用navicat等工具来连接mysql:

在这里插入图片描述

2、部署tomcat

步骤如下:

  1. 搜索tomcat镜像

     docker search tomcat
    
  2. 拉取mysql镜像

    docker pull tomcat         # 直接拉取最新版
    
  3. 运行容器设置端口映射

    # 创建tomcat目录用于存储tomcat数据信息
    mkdir ~/tomcat
    cd ~/tomcat
    
    docker run -id --name c_tomcat  \
    -p 8080:8080  \
    -v ~/tomcat:/usr/local/tomcat/webapps \
    tomcat 
    

3、部署nginx

  1. 拉取nginx镜像

    docker pull nginx         # 直接拉取最新版
    
  2. 运行容器设置端口映射

    mkdir -p ~/nginx/conf
    cd ~/nginx/conf
    
    
    vim nginx.conf  
    # 在~/nginx/conf下创建nginx.conf配置文件,将下面的内容黏贴到nginx.conf中
    ----------------------------------------------------------------
    
    user  nginx;
    worker_processes  auto;
    
    error_log  /var/log/nginx/error.log notice;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    }
    
    
    docker run -id --name=c_nginx \
    -p 80:80  \
    -v ~/nginx/conf/nginx.conf:/etc/nginx/nginx.conf  \
    -v ~/nginx/conf/logs:/var/log/nginx  \
    -v ~/nginx/conf/html:/usr/share/nginx/html  \
    nginx
    

4、部署redis

步骤如下:

  1. 拉取redis镜像

    docker pull redis         # 直接拉取最新版
    
  2. 运行容器设置端口映射

    docker run -id --name c_redis -p 6379:6379 redis
    
  3. 使用外部机器连接redis

    redis-cli -h 宿主机ip -p 6379
    

四、构建自己的镜像

常用地创建镜像的方式有两种,分别是:将容器提交为一个镜像、使用Dockerfile创建镜像。

1、Docker镜像原理

首先先思考几个问题:

  1. Docker 镜像本质是什么?
  2. Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G?
  3. Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB

操作系统的组成部分:

  • 进程调度子系统
  • 进程通信子系统
  • 内存管理子系统
  • 设备管理子系统
  • 文件管理子系统
  • 网络通信子系统
  • 作业控制子系统

Linux文件系统由bootfs和rootfs两部分组成

  • bootfs:包含bootloader(引导加载程序)和 kernel(内核)
  • rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件

不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等。

在这里插入图片描述

Docker镜像是由特殊的文件系统叠加而成,最底端是 bootfs,并使用宿主机的bootfs ,第二层是 root文件系统rootfs,称为base image,然后再往上可以叠加其他的镜像文件。

联合文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。

一个镜像可以放在另一个镜像的上面。位于下面的镜像称为父镜像,最底部的镜像成为基础镜像。当从一个镜像启动容器时,Docker会在最顶层加载一个读写文件系统作为容器

在这里插入图片描述

因此上面思考的答案是:

  1. Docker 镜像本质是什么?

    ​ :是一个分层的文件系统

  2. Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G?

    ​ : Centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层

  3. Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB

    ​ : 由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的tomcat镜像大小500多MB

2、提交容器为镜像

我们可以将一个容器转为一个镜像。也可以将一个镜像生成一个本地的压缩文件,在1.6节已经介绍。

在这里插入图片描述

我们从远程仓库拉取的官方的ubuntu系统是很纯净的,里面去除了很多不必要的软件,甚至连sudo命令的没有。我们可以运行一个从官网拉取的镜像,并在容器中安装vim、GCC、make等工具,然后将该容器提交为一个镜像。那么之后根据这个镜像运行新的容器时,容器中就会有这些工具了。

docker commit 容器名 或 ID 生成的镜像标签

# 例如
docker commit ubuntu1 myubuntu:lastest 

3、使用Dockerfile创建镜像

Dockerfile是一个文本格式的配置文件,用户可以使用Dockerfile来快速创建自定义的镜像。Dockerfile一般由一行行指令组成,并且支持以#开头的注释行;每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像;对于开发人员:可以为开发团队提供一个完全一致的开发环境;对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了;对于运维人员:在部署时,可以实现应用的无缝移植;

一般而言,Dockerfile主体内容分为四部分:基础镜像信息、维护者信息、镜像操作指令和容器启动时执行指令。

在这里插入图片描述

Dockerfile相关命令:

关键字 作用 备注
FROM 指定父镜像 指定dockerfile基于哪个image构建
MAINTAINER 作者信息 用来标明这个dockerfile谁写的
LABEL 标签 用来标明dockerfile的标签 可以使用Label代替Maintainer 最终都是在docker image基本信息中可以查看
RUN 执行命令 执行一段命令 默认是/bin/sh 格式: RUN command 或者 RUN [“command” , “param1”,“param2”]。RUN命令是在镜像构建时执行的。
CMD 容器启动命令 提供启动容器时候的默认命令 和ENTRYPOINT配合使用.格式 CMD command param1 param2 或者 CMD [“command” , “param1”,“param2”]。CMD命令是在容器启动时执行的。
ENTRYPOINT 入口 指定镜像的默认入口命令
COPY 复制文件 build的时候复制文件到image中
ADD 添加文件 build的时候添加文件到image中 不仅仅局限于当前build上下文 可以来源于远程服务,添加压缩文件时会自动解压。
ENV 环境变量 指定build时候的环境变量 可以在启动的容器的时候 通过-e覆盖 格式ENV name=value
ARG 构建参数 构建参数 只在构建的时候使用的参数 如果有ENV 那么ENV的相同名字的值始终覆盖arg的参数
VOLUME 定义外部可以挂载的数据卷 指定build的image那些目录可以启动的时候挂载到文件系统中 启动容器的时候使用 -v 绑定 格式 VOLUME [“目录”]
EXPOSE 暴露端口 定义容器运行的时候监听的端口 启动容器的使用-p来绑定暴露端口 格式: EXPOSE 8080 或者 EXPOSE 8080/udp
WORKDIR 工作目录 指定容器内部的工作目录 如果没有创建则自动创建 如果指定/ 使用的是绝对地址 如果不是/开头那么是在上一条workdir的路径的相对路径
USER 指定执行用户 指定build或者启动的时候 用户 在RUN CMD ENTRYPONT执行的时候的用户
HEALTHCHECK 健康检查 指定监测当前容器的健康监测的命令 基本上没用 因为很多时候 应用本身有健康监测机制
ONBUILD 触发器 当存在ONBUILD关键字的镜像作为基础镜像的时候 当执行FROM完成之后 会执行 ONBUILD的命令 但是不影响当前镜像 用处也不怎么大
STOPSIGNAL 发送信号到宿主机 该STOPSIGNAL指令设置将发送到容器的系统调用信号以退出。
SHELL 指定执行脚本的shell 指定RUN CMD ENTRYPOINT 执行命令的时候 使用的shell

Dockerfile构建命令:

docker build -f ./Dockerfile -t myimage .

# -f 参数用于指定dockerfile的位置,如果在当前目录下切名字为Dockerfile,也可以不指定
# -t target 用于指定生成的镜像名
# .为构建的目录
例1:构建Springboot项目的镜像:

写了一个简单的springboot程序:

在这里插入图片描述

可以在浏览器中访问的到:

在这里插入图片描述

构建步骤:

1.将项目打包为jar文件,并上传到linux的一个目录下,例如/home/mgh/docker_springboot文件下:

mkdir ~/docker_springboot

2.创建Dokcerfile文件:

vim Dockerfile

3.写Dockerfile:

dockerfile 内容如下

# 由于springboot项目依赖java jdk,因此需要有jdk的环境。也可以是ubuntu或centos,但是其中没有java环境,还需要安装
FROM java:8

# 作者信息,也可以不要
MAINTAINER author<author@hdu.edu.cn>

# 将当前目录下的jar包添加到镜像中,并命名为app.jar
ADD springboot_test-0.0.1-SNAPSHOT.jar app.jar

# 运行springboot项目 也可以是CMD ["java", "-jar", "app.jar"]
CMD java -jar app.jar

4.构建镜像:

docker build -t springboot_test .

5.构建成功

在这里插入图片描述

6.运行容器

 docker run -id -p 8080:8080 springboot_test

7.在浏览器中访问

在这里插入图片描述

例2:构建C++程序

1.创建目录、写一个helloworld程序

mkdir ~/cpp_docker
vim hello.cpp

程序如下,每隔一秒打印一次hello,world

#include <iostream>
#include <unistd.h>

using namespace std;

int main()
{
    while(1)
    {
        cout << "hello,world!" << endl;
        sleep(1);
    }

    return 0;
}

2.创建Dockerfile文件并写入

vim Dockerfile

# 内容如下:

# 基础镜像
FROM ubuntu:18.04

MAINTAINER author<author@hdu.edu.cn>

# 设置环境变量
ENV MYPATH /usr/local/test

# 设置工作目录,设置工作目录后,启动容器,容器所在目录就是工作目录
WORKDIR $MYPATH

# 将当前文件夹下的cpp文件拷贝到工作目录
COPY hello.cpp $MYPATH

# 安装g++ 以及 编译cpp文件。也可以将这三个命令分开写成三条,但是会生成三层,所以不建议
# 在安装软件的时候,系统可能会让你输入y或n来同意或拒绝安装,使用-y参数就是同意安装。不然可能会失败。
RUN apt-get update &&  \
    apt-get -y install g++ && \
    g++ hello.cpp -o hello

# 容器启动时执行的命令
CMD ["./hello"]

3.构建镜像

docker build -t cpp_test .

4.运行容器

docker run -it cpp_test

在这里插入图片描述

可以看到容器中在打印hello,world。但是退出不了了,可以使用docker stop将这个容停止。

例3:构建Golang程序

将使用gin框架的一个web程序构建为docker镜像:

1.golang代码:

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)


func main()  {
	engine := gin.Default()

	engine.GET("/jige", func(context *gin.Context) {
		data := map[string]interface{}{
			"name" : "kunkun",
			"age" : 23,
			"hobby" : "sing jump rap",
		}
		context.JSON(http.StatusOK, data)

	})

	engine.Run("0.0.0.0:8080")
}

go.mod

go mod init
go mod tidy

2.将程序打包上传到linux的一个文件中

mkdir ~/docker_golang
#程序文件名 gin_json

3.创建Dockerfile

vim Dockerfile

# dockerfile内容如下
# 基础镜像
FROM golang

MAINTAINER author <author@hdu.edu.cn>

# 设置环境变量
ENV GO111MODULE on
# 设置golang代理否则下载gin框架很可能会失败
ENV GOPROXY https://goproxy.cn

# 设置工作目录
WORKDIR /go/src/gin_json/

# 把当前目录下所以文件拷贝到容器的工作目录
COPY . .

# 安装gin框架依赖
RUN go mod tidy

# 容器启动运行程序
CMD go run main.go

4.构建镜像

docker build -t gotest .

5.运行容器

docker run -id -p 9090:8080 gotest

6.浏览器访问页面

在这里插入图片描述

4、配置指令详细介绍:

1.FROM :

指定所创建镜像的基础镜像,比如JAVA程序依赖于java jdk,因此可以选择一个带有java jdk的镜像作为基础镜像。

格式:FROM image 或 FROM image:tag

任何Dockerfile中第一条指令必须为FROM指令。并且,如果在同一个Dockerfile中创建多个镜像时,可以使用多个FROM指令。

为了保证镜像精简,可以选用体积较小的镜像如Alpine或Debian作为基础镜像。

2.ARG :

定义创建镜像过程中使用的变量。

格式:ARG key val 或 ARG key =val

当镜像构建完成后,ARG定义的变量将不再存在(ENV指定的变量将在镜像中保留)。

3.ENV :

指定环境变量,在镜像生成过程中会被RUN指令使用,在镜像启动的容器中也会存在。

格式:ENV key val 或 ENV key=val

指令指定的环境变量在运行时可以被覆盖掉,如:docker run --env key=val built_image

4.LABEL :

LABEL指令可以为生成的镜像添加元数据标签信息。

格式:LABEL key=value key=value …

5.EXPOSE :

声明镜像内服务监听的端口。

格式:EXPOSE port …

例如:

EXPOSE 22 80 8080

该指令只是起到声明作用,并不会自动完成端口映射。

6.ENTRYPOINT :

指定镜像的默认入口命令,该入口命令会在启动容器时作为根命令执行,所有传入值作为该命令的参数。

支持两种格式:

ENTRYPOINT [“executable”, “param1”, “param2”] exec调用执行

ENTRYPOINT command param1 param2 shell中执行

此外,CMD指令指定值将作为根命令的参数。每个Dockerfile中只能有一个ENTRYPOINT,当指定多个时,只有最后一个生效。

7.CMD :

CMD指令用来指定启动容器时默认执行的命令。

支持三种格式:

CMD [“executable”, “param1”, “param2”] 相当于执行executable param1 param2

CMD command param1 param2 在默认的shell中执行,提供给需要交互的应用

CMD [“param1”, “param2”] 提供给ENTRYPOINT的默认参数

每个Dockerfile只能有一条CMD命令。如果指定了多条命令,只有最后一条会被执行。如果用户启动容器时手动指定了运行的命令,则会覆盖掉CMD指定的命令。

例如:

在上面的构建C++程序中,指定了CMD运行hello程序:CMD [“./hello”]

因此如果在运行容器时指定了/bin/bash,那么./hello将会被覆盖掉,hello程序也就不会执行 : docker run -it cpp_test /bin/bash

9.VOLUME :

创建一个数据卷挂载点。

格式: VOLUME [“/data”]

运行容器时可以从本地主机或其它容器挂载数据卷,一般用来存放数据库和需要保持的数据或一些配置文件等。

10.WORKDIR :

为后续的RUN、CMD、ENTRYPOINT指令配置工作目录

格式: WORKDIR dir

在WORKDIR指令中最好使用绝对路径。

11.RUN :

运行指定命令。

格式:

RUN command 或 RUN [“executable”, “param1”, “param2”]

注意后者指令将会被解析为JSON数组,因此必须用双引号。前者默认在shell终端中运行命令,即/bin/bash -c;后者使用exec执行,不会启动shell环境。

指定使用其它终端类型可以通过第二种方式实现,例如 RUN [“/bin/bash”, “-c”, “echo hello”]。

每条RUN命令将在当前基础镜像上执行指定命令,并提交为新的镜像层,如果有多条RUN命令,分开来写将会产生很多层镜像层,因此最后将他们写成一条命令,可以用 \ 来换行。例如:

RUN apt-get update \

​ && apt-get install -y libsnappy-dev zliblg-dev libbz2-dev \

​ && rm -rf /var/cache/apt \

​ && rm -rf /var/lib/apt/lists/*

12.ADD :

添加内容到镜像。

格式: ADD src dest

该命令将复制指定的src路径下内容到容器中的dest路径下。

其中src可以是Dockerfile所在目录的一个相对路径(文件或目录);也可以是一个URL;还可以是一个tar文件,tar文件将会被自动解压为目录。路径支持正则表达式,例如:

ADD *.cpp /code/

13.COPY :

复制内容到镜像。

格式:COPY src dest

复制本地主机的src下内容到镜像中的dest。目录不存在时,会自动创建。

路径同样支持正则表达式。

COPY与ADD命令功能相似,当使用本地目录为源目录时,推荐使用COPY。

注意:在构建镜像时最好保证指定目录(命令为:docker build -t test ., 最后那个.就是指定当前目录为构建目录)下没有其它不需要的文件,因为在构建镜像时是由Docker守护进程来执行的,因此客户端将会把指定目录下的所有内容都发送给Docker守护进程,如果当前目录下存在不需要的文件,将会拖慢镜像的构建。

5.最佳实践

所谓最佳实践,就是从需求出发,来定制适合自己、高效的镜像。

精简镜像用途:尽量让每个镜像的用途都比较单一,避免构造大而复杂。

选用合适的基础镜像:容器的核心是应用。选择过大的父镜像(如Ubuntu系统镜像)会造成最终生成应用镜像的臃肿,推荐选用瘦身过的应用镜像(如node:slim),或者较为小巧的系统镜像(如alpine、busybos或debian);

正确使用版本号:使用明确的版本号信息,如1.0,2.0,而非依赖于默认的lastest。通过版本号可以避免环境不一导致的问题;

减少镜像层数:尽量合并RUN、AD和COPY指令。

**及时删除临时文件和缓存文件:**特别是在执行apt-get命令后,/var/cache/apt下面会缓存了一些安装包;

提高生成速度:减少内容目录下不必要的文件。

Docker进阶(Docker网络、Docker Compose)

Logo

更多推荐