Docker 安装、常用命令、应用部署


目录
  • Docker 安装
    • 1)安装
    • 2)启动
    • 3)镜像加速器
  • Docker 常用命令
    • 1)Docker 进程相关命令
    • 2)Docker 镜像相关命令
      • docker search:查找镜像仓库中的镜像
      • docker pull:下载镜像
      • docker inspect:查看镜像/容器的详细信息
      • 在 hub.docker.com 上查找镜像
      • docker images:查看本地镜像
      • docker rmi:删除本地镜像
      • docker history:查看镜像构建历史
      • docker save:导出镜像
      • docker load:导入镜像
      • 镜像重命名
    • 3)Docker 容器相关命令
      • docker run:启动容器
      • 容器退出
      • docker ps:查看当前容器状态
      • docker pause:暂停容器
      • docker stop:停止容器
      • docker exec:进入容器
      • docker create:创建容器
      • docker rename:容器重命名
      • docker log:查看容器日志
      • docker rm:删除容器
      • docker commit:生成镜像
      • docker top:查看容器中运?的进程
      • docker stats:查看资源占?
  • Docker 容器的数据卷(Volumn)
    • 什么是数据卷?
    • 配置数据卷
    • 数据卷容器
  • Docker 应用部署
    • 端口映射问题
      • 防火墙配置
      • 端口映射配置
        • 随机映射:-P
        • 随即映射:-P
    • 部署 MySQL
    • 部署 Tomcat
    • 部署 Nginx
    • 部署 Redis


Docker 安装

  • Docker 可以运行在 MAC、Windows、CentOS、UBUNTU 等操作系统上。

  • 官网:https://www.docker.com

1)安装

CentOS 安装方法示例:

# 切换管理员权限
su root

# 安装 Docker 依赖
yum install -y yum-utils device-mapper-persistent-data lvm2

# 配置依赖下载源
yum-config-manager --add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装 docker
yum makecache fast && yum -y install docker-ce

2)启动

Docker 引擎启停操作:

# 启动
systemctl start docker
# 重启
systemctl restart docker
# 开机自启动
systemctl enable docker
# 运行状态
systemctl status docker

3)镜像加速器

默认情况下从 docker hub 上下载 docker 镜像的速度太慢,因此一般都会配置镜像加速器:

  • USTC:中科大镜像加速器(https://docker.mirrors.ustc.edu.cn)
  • 阿里云
  • 网易云
  • 腾讯云
# 添加 registry-mirrors
vim /etc/docker/daemon.json

# 内容
{
  "registry-mirrors": ["https://registry.docker-cn.com"]
}

# 重载 docker 的配置文件
systemctl daemon-reload

# 重启 Docker
systemctl restart docker 

# 查看配置
docker info 

Docker 常用命令

image


1)Docker 进程相关命令

Docker 信息相关命令

# Docker 版本信息
docker version
# Docker 系统信息
docker info

Docker 启停相关命令

# 启动 Docker 服务
systemctl start docker

# 停止 Docker 服务
systemctl stop docker

# 重启 Docker 服务
systemctl restart docker

# 查看 Docker 服务状态
systemctl status docker

# 设置开机启动 Docker 服务
systemctl enable docker

2)Docker 镜像相关命令

docker search:查找镜像仓库中的镜像

# 比如想要搜索具有 nginx 功能的容器
docker search nginx

image

  1. 第一列镜像名称,如果没有路径符号”/”,说明在默认路径中,如果有路径,说明在子仓库中。
  2. 第二列描述,简要说明该镜像的用途和特点。如果想要完整显示说明,可以增加参数 --no-trunc。
  3. 第三列是点赞数,类似于 git 上的点赞。
  4. 第四列标明是否为官方发布。
  5. 第五列是自动构建,是用 webhook 探测源码的变化,一旦有变化就自动生成新的版本镜像。

docker pull:下载镜像

从 Docker 仓库下载镜像到本地,镜像名称格式为名称:版本号,如果版本号不指定则是最新的版本。

docker pull nginx

如下图所示,将会下载该镜像。注意看该镜像会有多个分层,之后再下载其它镜像的时候,有可能部分层级可以复用,不需要全部下载。

image

另外注意箭头指的位置,由于 docker pull nginx 没有指定 tag(版本),会使用默认的版本下载。

再尝试下载 alpine 环境,alpine 是一款轻量级操作系统,只有 5M 左右。很多镜像制作都会选择 alpine 作为基础镜像。这里仅下载一个纯净的 alpine,作为后续演示使用。

docker pull alpine

注意查看下图中,docker pull 命令后面的 nginx 跟了 tag,可以看出,tag 不仅仅包含了版本号,还包含了主要的特性。

另外看箭头所指,之前下载过 alpine 的基本镜像,所以基于 alpine 的 nginx 会省略下载 alpine,复用之前下载的已存在分层。

image


docker inspect:查看镜像/容器的详细信息

docker inspect 镜像/容器名称

Docker Inspect 语法参考


在 hub.docker.com 上查找镜像

也可以在 hub.docker.com 网站上查找镜像,同时还可以看到该镜像的 tag 信息,选择合适的 tag 下载。

image

image

image

image

如上述步骤,找到其它版本的 tag,可以点击这个复制按钮,直接将命令复制出来。


docker images:查看本地镜像

docker images  # 查看本地所有的镜像
docker images –q  # 仅显示镜像id,常用于批量删除镜像

image


docker rmi:删除本地镜像

docker rmi 镜像id或镜像名称的前缀即可  # 删除指定的本地镜像
docker rmi `docker images -q`  # 删除所有本地镜像

本地镜像或者远程镜像仓库中的垃圾镜像越来越多时,需要进行清理删除。

image

图中存在没有 repository 和 tag 的镜像的原因是:使用相同的镜像名称构建新镜像时,由于 dockerfile 中的基础镜像或者 RUN 后面的命令有变化,就会导致旧的重名镜像变成没有 repository 和 tag 的情况。


docker history:查看镜像构建历史

docker history [options] IMAGE

通常只用一个参数 --no-trunc:不截断输出。

image

docker history 命令在查看自己构建的镜像时会相对容易和方便一些。官方镜像总要考虑大部分的需求,所以相对比较繁琐。


docker save:导出镜像

docker save 镜像名称 > 镜像名称.tar

docker load:导入镜像

docker load < 镜像名称.tar

镜像重命名

docker tag 镜像原来名称 镜像新名称

3)Docker 容器相关命令

  • 容器的本质是管理进程。启动容器必定会伴随容器内一个或者多个用户进程的启动,如果容器内的用户进程在启动后执行完毕或者崩溃,那么该容器就会退出。与虚拟机不同,虚拟机启动的是操作系统,如果没有用户进程,则会等待用户的登录和操作。

  • 最好是一个容器只执行一个进程,完成单一任务。

  • 虽然容器可以被登录,但最好不要登录进去操作,除非是为了修改镜像。


docker run:启动容器

docker run 参数
# -it 创建的容器一般称为交互式容器
# -id 创建的容器一般称为守护式容器

参数说明

  • -i:保持容器运行
    • 通常与 -t 同时使用。加入 it 这两个参数后,容器创建后会自动进入容器中。
    • 退出容器后,容器自动关闭。
  • -t:为容器重新分配一个伪输入终端
    • 通常与 -i 同时使用。
  • -d:以守护(后台)模式运行容器
    • 创建一个容器并在后台运行,需要使用 docker exec 进入容器。
    • 退出容器后,容器不会关闭。
  • --name:为创建的容器命名。

示例:docker run -it alpine

image

如图所示已经进入了容器的 shell,可以操作查看这个 shell:

  • uname -a 查到系统内核和宿主机的一致,说明容器使用底层宿主机的内核。
  • pwd 和 ls 可以看到此时 shell 的目录结构和宿主机不一致。

容器是用来管理进程的,在虚拟机的宿主机中,执行 ps 是看不到虚拟机内部的进程的。但是容器不一样,在容器的宿主机中执行 ps,是可以看到容器执行的进程的。从本质上看,容器仅仅是在宿主机中把进程启动起来,并且进行资源隔离。


容器退出

  • 使用 ctrl+dexit 命令,容器都会退出。ctrl+d 或者 exit 相当于结束当前 shell,在未指定命令情况下启动容器时,相当于仅启动了 /bin/bash,退出后结束 bash,容器退出。

  • 使用 ctrl+q+p 退出,会保持该容器在后台运行,容器不会结束。


docker ps:查看当前容器状态

docker ps  # 查看正在运行的容器
docker ps –a  # 查看所有容器
docker ps –qa  # 仅显示 id 号,常用于批量删除容器

image

如上图所示,不加任何参数,查看正在运行的容器:目前没有正在运行的容器。

  • CONTAINER ID:容器的 ID。
  • IMAGE:启动使用的镜像。
  • COMMAND:启动容器时传入的命令。
  • CREATED:创建时间。
  • STATUS:容器状态。
  • PORTS:端口映射情况。
  • NAMES:容器的名称,如果没有指定,会随机分配。

image

-a 参数可以查看所有状态的容器,包括停止、退出等状态的容器。

如上图所示目前有一个容器,但状态是已经退出。


docker pause:暂停容器

docker pause CONTAINER [CONTAINER]   # 暂停
docker unpause CONTAINER [CONTAINER]   # 恢复

image

如图所示,docker pause 时用的容器 mynginx 进入了暂停状态。恢复的时候用的容器 id,容器恢复正常状态。注意恢复后的状态开启时间并没有重新计时,而是继续计时,暂停时间也会算进开机时间。

如果使用容器 id 则只要用 id 的前若干位即可,只要前几位没有冲突,通常使用三位。这个规则适用于整个 docker 的场景。

Paused 状态意味着暂停、挂起,但是容器管理的进程并没有停止。整体上更像是虚拟机的快照暂停方式,把当前容器做个快照放在磁盘中,然后释放该容器的资源。等需要恢复的时候,把容器的内容从磁盘中读出来重新进入内存。底层使用的是 cgroup 的 freezer 能力。


docker stop:停止容器

docker stop CONTAINER [CONTAINER]  # 停止
docker start CONTAINER [CONTAINER]  # 启动
docker restart CONTAINER [CONTAINER]  # 重启

image

这三个状态类比虚拟机,就是关机、启动和重启。stop 后容器管理的进程会彻底停止、清理内存;start 启动容器时会沿用容器 run 或者 create 时候的参数。

这和虚拟机类似的操作过程相同,磁盘中的内容会被保存,但是内存中的内容会被清理掉。


docker exec:进入容器

对于后台执行的容器或者容器的输出日志,我们都有查看的需求。

方式一:docker attach(不推荐使用)

该命令使用不当的话,会导致容器中的进程结束运行,进而容器退出。使用的时候一定加上 --sig-proxy=false 参数。

方式二:docker exec(推荐使用)

docker exec [options] CONTAINER CMD

该命令用途是在运行中的容器里执行命令,当然也可以在运行的容器中执行 /bin/bash。

注意 exec 不默认传参数,必须跟参数:

image

上图中,首先在后台启动一个交互式 alpine 容器,并查看这个容器状态,确认运行中。后续操作需要用到容器名称,所以重命名一下。接着让这个容器执行一下 echo 命令。可以看到执行后容器输出 hello,并且不会退出,仍然在运行状态中。

执行 /bin/bash,就可以进到容器中进行操作,注意 /bin/bash 需要交互和打开标准输入:

image

如上图中的报错,最初执行 docker exec -it myalpine /bin/bash,由于 alpine 中没有 bash 这个命令,所以报错。

使用 /bin/sh 后就可以进入容器执行命令了,退出后不影响原容器运行。

注意很多镜像里面并不带 kill 命令,但是如果带 kill 命令并且在 exec 中执行 kill 主进程操作,或者执行了主进程的停止操作,会导致容器直接退出。


docker create:创建容器

docker create [option] IMAGE [CMD]

docker run 命令相当于执行了 create 和 start 两个命令。


docker rename:容器重命名

docker rename 容器原来名称 容器新名称

docker log:查看容器日志

docker logs [options] CONTAINER

docker rm:删除容器

如果容器是运行状态则删除失败,需要停止容器才能删除。

docker rm [OPTIONS] 容器名称/id [CONTAINER...]

OPTIONS 说明:

  • 不加参数情况下,可以删除已经停止的容器。
  • -f:通过 SIGKILL 信号删除一个正在运行的容器。
  • -l:移除容器间的网络,而非容器本身。
  • -v:删除与容器映射的目录。

宿主机运行一段时间后,会有大量已经停止的容器,如果需要批量删除,可以使用以下命令:

docker rm $(docker ps -qa)

image

最终只剩下运行中的容器。当然也可以使用 -f 参数删除所有容器,慎重使用。


docker commit:生成镜像

若以交互模式修改了容器内容,需要 commit 成新的镜像。

1)修改容器内容:

[root@MiWiFi-R3P-srv tmp]# docker  run -it centos
[root@e59e110aaf47 /]# yum install -y nginx
[root@e59e110aaf47 /]# vi /etc/nginx/nginx.conf  # 在全局配置中加入"daemon off;"

2)退出容器:

image

3)执行 commit 命令:

image

4)运行中的容器也可以 commit,并且容器层的数据也会保留:

image

  1. 注意上图中,启动 nginx:v7commit 需要以 nginx 的启动命令,否则容器会退出;
  2. 使用 docker exec 进入容器,并编辑内容;
  3. 本次 commit 使用和之前完全一样的镜像名称和 tag,所以在名称前加一个 test 目录;
  4. 接下来启动这个镜像,看 echo 修改的内容和文件会不会存在:

image


docker top:查看容器中运?的进程

docker top 容器名称

docker stats:查看资源占?

docker stats 容器名称

Docker 容器的数据卷(Volumn)

什么是数据卷?

问题现象

  1. Docker 容器删除后,在容器中产生的数据也会随之销毁。
  2. Docker 容器和外部机器可以直接交换文件吗?不能。
  3. 容器之间想要进行数据交互?

上述问题的解决方案:数据卷

image

什么是数据卷?

  • 数据卷是宿主机中的一个目录或文件。
  • 当容器目录和数据卷目录绑定后,对方的修改会立即同步。
  • 一个数据卷可以被多个容器同时挂载。
  • 一个容器也可以被挂载多个数据卷。

数据卷的作用

  1. 容器数据持久化。
  2. 容器和外部机器间接通信。
  3. 容器之间数据交换。

配置数据卷

创建启动容器时,使用 –v 参数设置数据卷:

docker run ... –v 宿主机目录(文件):容器内目录(文件) ... 

注意:

  1. (两边)目录必须是绝对路径
  2. 如果(两边)目录不存在,会自动创建

数据卷容器

多容器进行数据交换

image

  1. c1 和 c2 容器可以同时通过宿主机和 c3(数据卷容器)挂载数据卷。
  2. 即使 c3 挂了,也不影响 c1 和 c2 与宿主机同步数据。

配置方法:创建一个容器,挂载一个目录,让其他容器继承自该容器(--volume-from)

# 创建启动 c3 数据卷容器,使用 –v 参数设置数据卷
docker run –it --name=c3 –v /volume centos:7 /bin/bash  # 注意这里只需要容器目录即可,宿主机会随机分配挂载目录

# 创建启动 c1 c2 容器,使用 –-volumes-from 参数设置数据卷
docker run –it --name=c1 --volumes-from c3 centos:7 /bin/bash
docker run –it --name=c2 --volumes-from c3 centos:7 /bin/bash

Docker 应用部署

端口映射问题

如果外部机器要访问到容器中的应用,首先需要解决端口映射问题(容器需要映射端口才能和外部通信)。提到端口映射,就涉及到容器的网络和主机网络之间的关系。

  1. 容器内的网络服务和外部机器不能直接通信
  2. 外部机器和宿主机可以直接通信
  3. 宿主机和容器可以直接通信
  4. 因此,当容器中的网络服务需要被外部机器访问时,可以将容器中提供服务的端口映射到宿主机的端口上,外部机器访问宿主机的该端口,从而间接访问容器的服务。这种操作称为:端口映射

image


防火墙配置

示例:Centos 8 使用 firewalld 服务管理转发规则。firewalld 服务必须打开,不然 docker 无法创建端口转发,但是打开后会拦截 80、8080 和 32000 以上的端口,导致 web 端口全都无法通过,所以需要用 firewalld 打开端口限制。

# 打开防火墙
systemctl start firewalld.service

# 防火墙开机启动
systemctl enable firewalld.service

# 将主机网卡加入信任域
firewall-cmd --permanent --zone=trusted --change-interface=enp0s3 

# 增加80口信任
firewall-cmd --add-port=80/tcp --permanent

# 增加 8080 端口信任
firewall-cmd --add-port=8080/tcp --permanent

# 增加 32001--65010 口信任
firewall-cmd --add-port=32001-65010/tcp --permanent

# 重新加载配置文件
firewall-cmd --reload

端口映射配置

端口映射在 docker run 或 create 时配置,参数使用 -P(随机映射)或 -p(指定映射)。

随机映射:-P

docker 会给宿主机上所有 IP(0.0.0.0)分配一个 32000 以上的随机端口,映射到容器内对外提供服务的端口。

image

如上图所示,使用 docker ps,可以看到宿主机 32769 端口映射到容器 80 端口。

再查看宿主机 IP,用此 IP 加 32769 端口访问 nginx 的默认页面(注意宿主机的防火墙需要关闭或者设置):

image

image

可以看到通过宿主机 IP 加上随机分配的端口,就可以访问容器提供的 web 服务。


随即映射:-P

image

注意事项:

  • 选择指定端口进行映射时,宿主机端口不能被占用。
  • 如果容器启动时绑定的仅是宿主机 IP,则宿主机本机访问 127.0.0.1 的 80 端口是不通的(ps 中 0.0.0.0:80 才代表所有 IP 均被绑定)。

部署 MySQL

  1. 搜索 mysql 镜像:
docker search mysql
  1. 拉取 mysql 镜像:
docker pull mysql:5.6
  1. 创建容器,设置端口映射、目录映射:
# 在/root目录下创建mysql目录用于存储mysql数据信息
mkdir ~/mysql
cd ~/mysql
docker run -id \
-p 3307:3306 \
--name=c_mysql \
-v $PWD/conf:/etc/mysql/conf.d \
-v $PWD/logs:/logs \
-v $PWD/data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
  • 参数说明:
    • -p 3307:3306:将容器的 3306 端口映射到宿主机的 3307 端口
    • -v $PWD/conf:/etc/mysql/conf.d:将主机当前目录下的 conf/my.cnf 挂载到容器的 /etc/mysql/my.cnf
    • -v $PWD/logs:/logs:将主机当前目录下的 logs 目录挂载到容器的 /logs
    • -v $PWD/data:/var/lib/mysql :将主机当前目录下的 data 目录挂载到容器的 /var/lib/mysql
    • -e MYSQL_ROOT_PASSWORD=123456:初始化 root 用户的密码
  1. 进入容器,操作 mysql :
docker exec –it c_mysql /bin/bash
  1. 使用外部机器连接容器中的 mysql :
    image

部署 Tomcat

  1. 搜索 tomcat 镜像:
docker search tomcat
  1. 拉取 tomcat 镜像:
docker pull tomcat
  1. 创建容器,设置端口映射、目录映射:
# 在 /root 目录下创建 tomcat 目录用于存储 tomcat 数据信息
mkdir ~/tomcat
cd ~/tomcat
docker run -id --name=c_tomcat \
-p 8080:8080 \
-v $PWD:/usr/local/tomcat/webapps \
tomcat
  • 参数说明:

    • -p 8080:8080:将容器的 8080 端口映射到主机的 8080 端口

      -v $PWD:/usr/local/tomcat/webapps:将主机中当前目录挂载到容器的 webapps

  1. 使用外部机器访问 tomcat :
    image

部署 Nginx

  1. 搜索 nginx 镜像:
docker search nginx
  1. 拉取 nginx 镜像:
docker pull nginx
  1. 创建容器,设置端口映射、目录映射:
# 在 /root 目录下创建 nginx 目录用于存储 nginx 数据信息
mkdir ~/nginx
cd ~/nginx
mkdir conf
cd conf
# 在 ~/nginx/conf/ 下创建 nginx.conf 文件,粘贴以下内容
vi nginx.conf
  • nginx.conf 配置:
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
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 $PWD/conf/nginx.conf:/etc/nginx/nginx.conf \
-v $PWD/logs:/var/log/nginx \
-v $PWD/html:/usr/share/nginx/html \
nginx
  • 参数说明:
    • -p 80:80:将容器的 80 端口映射到宿主机的 80 端口
    • -v $PWD/conf/nginx.conf:/etc/nginx/nginx.conf:将主机当前目录下的 /conf/nginx.conf 挂载到容器的 /etc/nginx/nginx.conf
    • -v $PWD/logs:/var/log/nginx:将主机当前目录下的 logs 目录挂载到容器的/var/log/nginx
  1. 使用外部机器访问 nginx :
    image

部署 Redis

  1. 搜索 redis 镜像:
docker search redis
  1. 拉取 redis 镜像:
docker pull redis:5.0
  1. 创建容器,设置端口映射:
docker run -id --name=c_redis -p 6379:6379 redis:5.0
  1. 使用外部机器连接 redis :
./redis-cli.exe -h 192.168.149.135 -p 6379