一、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

更多推荐