Docker 入门

背景

环境(切换/配置)麻烦

项目(产品)过程中,有如下3个环境:

研发写代码的环境叫做开发环境。

测试进行验证的环境叫做测试环境。

用户部署使用的环境叫做生产环境。

其实在很多时候,大量的时间浪费在了环境上。

  • 如果我现在重装了系统,我想要跑我的jar包,我得去安装一下JDK、Tomcat、MySQL等,并配置各种环境变量才能跑起来。

  • 好不容易开发环境没问题了,但是到测试环境就是各种bug。

  • 好不容易在测试环境验证通过了,但是在生产环境就各种出错。

应用之间需要隔离

比如有两个web应用,这两个应用部署在同一台服务器上,那可能会出现什么问题?

  • 如果一个应用出现了问题,导致CPU占100%。那另一个应用也会受到影响,跟着一起宕机了。

  • 这两个应用是不同技术栈的应用,比如一个jdk,一个php。这两个应用各种的依赖软件都安装在同一个服务器上,可能就会造成各种冲突/无法兼容,这可能调试就非常麻烦了。

使用Docker 进行解决

  1. 将一整套环境打包封装成镜像,无需重复配置环境,解决环境带来的种种问题。从开发的角度来看就是三步走:构建,发布,运行。其中关键步骤就是构建环节,即打包镜像文件。从测试和运维的角度来看,那就只有两步:复制,运行。有了这个镜像,那么想复制到哪运行都可以,完全和平台无关了。
  2. Docker容器间是进程隔离的,相互之间互不影响
  3. Docker的性能几乎和原生系统无异,并且系统支持量很高。

概述

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

Docker是容器虚拟化技术,可以有多个容器(可以不同功能)且相互隔离,互不影响。容器没有自己的内核,直接运行于宿主主机的内核。

Docker优点

  • 简化程序: Docker 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,便可以实现虚拟化。Docker改变了虚拟化的方式,使开发者可以直接将自己的成果放入Docker中进行管 理。方便快捷已经是 Docker的最大优势,过去需要用数天乃至数周的任务,在Docker容器的处理下,只需要数秒就 能完成。

  • 避免选择恐惧症: 如果你有选择恐惧症,还是资深患者。Docker 帮你打包你的纠结!比如 Docker 镜像;Docker 镜 像中包含了运行环境和配置,所以 Docker 可以简化部署多种应用实例工作。比如 Web 应用、后台应用、数据库应 用、大数据应用比如 Hadoop 集群、消息队列等等都可以打包成一个镜像部署。

  • 节省开支: 一方面,云计算时代到来,使开发者不必为了追求效果而配置高额的硬件,Docker 改变了高性能必然高 价格的思维定势。Docker 与云的结合,让云空间得到更充分的利用。不仅解决了硬件管理的问题,也改变了虚拟化 的方式。

容器和虚拟机

Docker 在容器的基础上,进行了进一步的封装,从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护。使得 Docker 技术比虚拟机技术更为轻便、快捷。

安装

在线安装

安装详细说明参考官方文档:https://docs.docker.com/get-docker,以 CentOS 7为例。

Docker 要求操作系统必须为64位,且centos内核版本为3.1及以上。

# 查看系统内核版本
uname -r

# 卸载旧版本
 yum remove docker \
             docker-client \
             docker-client-latest \
             docker-common \
             docker-latest \
             docker-latest-logrotate \
             docker-logrotate \
             docker-engine

# 安装 yum-utils 包
yum install -y yum-utils

# 设置 Docker 仓库
# 官方地址(比较慢)
yum-config-manager --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
# 阿里云地址(国内地址,相对更快)
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

# 安装 Docker 引擎
yum install docker-ce docker-ce-cli containerd.io


# 启动 docker 服务
systemctl start docker
# 查看 Docker 版本信息
docker version
# 查看 docker 服务状态
systemctl status docker
# 停止 docker 服务
systemctl stop docker
# 重启 docker 服务
systemctl restart docker
# 设置 docker 开机自启
systemctl enable docker

# 查看 Docker 的磁盘使用情况
docker system df

# 查看 Docker 的 CPU、内存、网络、IO 等使用情况
# 查看所有容器
docker stats -a
# 查看指定容器:docker stats 容器名称或容器ID
docker stats nginx

离线安装

# 下载地址
链接:https://pan.baidu.com/s/1S7B1PUxsybCT-BTGBM19OA?pwd=i65a 
提取码:i65a

# 解压 docker-19.03.9.tgz
tar -zxvf docker-19.03.9.tgz

# 将解压后目录 docker 目录中的所有文件复制到 /usr/bin 目录下
cd docker
cp * /usr/bin

# 将 docker.service 复制到 /etc/systemd/system 目录下
cp docker.service /etc/systemd/system

# 启动 docker 服务
systemctl start docker
# 查看 Docker 版本信息
docker version
# 查看 docker 服务状态
systemctl status docker
# 停止 docker 服务
systemctl stop docker
# 重启 docker 服务
systemctl restart docker
# 设置 docker 开机自启
systemctl enable docker

配置镜像加速

Docker 默认拉取镜像是从 https://hub.docker.com 拉取,国外地址拉取的速度比较慢。我们也可以配置国内镜像源,比如阿里云镜像加速器。访问地址 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors,复制加速器地址,如:https://xxxxxx.mirror.aliyuncs.com。

# 配置加速器
mkdir -p /etc/docker
vim /etc/docker/daemon.json
{
    "registry-mirrors": [
        "https://ung2thfc.mirror.aliyuncs.com"
    ]
}

# 重启 Docker Daemon
systemctl daemon-reload
# 重启 docker 服务
systemctl restart docker

下面列出国内常用的加速站点,排名不分先后,总体来说阿里云速度较稳定。

docker中国区官方镜像加速:

https://registry.docker-cn.com

网易镜像加速:

http://hub-mirror.c.163.com

中国科技大学镜像加速:

https://docker.mirrors.ustc.edu.cn

腾讯云镜像加速:

https://mirror.ccs.tencentyun.com

阿里云镜像加速:

https://ung2thfc.mirror.aliyuncs.com

镜像命令

官方文档:https://docs.docker.com/reference

查看镜像

docker images

# REPOSITORY    镜像在仓库中的名称
# TAG    镜像标签
# IMAGE ID    镜像 ID
# CREATED    镜像的创建日期
# SIZE    镜像大小
REPOSITORY           TAG       IMAGE ID       CREATED        SIZE
mysql                5.7       938b57d64674   3 weeks ago    448MB
redis                6.2.6     7faaec683238   5 weeks ago    113MB
nginx                1.20.1    c8d03f6b8b91   4 weeks ago    133MB
nacos/nacos-server   2.0.3     433eb51fef8d   3 months ago   1.05GB

这些镜像默认都是存储在 Docker 宿主机的 /var/lib/docker 目录下。

搜索镜像

# 从网络中查找需要的镜像:docker search 镜像名称
docker search mysql

# NAME    镜像名称
# DESCRIPTION    镜像描述
# STARS    用户评价
# OFFICIAL    是否为官方构建
# AUTOMATED    Docker Hub 自动构建
NAME                              DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
nginx                             Official build of Nginx.                        15800     [OK]       
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker con…   2093                 [OK]
richarvey/nginx-php-fpm           Container running Nginx + PHP-FPM capable of…   818                  [OK]
jc21/nginx-proxy-manager          Docker container for managing Nginx proxy ho…   273                  
linuxserver/nginx                 An Nginx container, brought to you by LinuxS…   159                  
tiangolo/nginx-rtmp               Docker image with Nginx using the nginx-rtmp…   144                  [OK]

拉取镜像

拉取镜像就是从中央仓库下载镜像到本地。

docker pull 镜像名:TAG
# 如果不声明 tag 镜像标签信息,则默认拉取当前 latest 版本
docker pull nginx:1.20.1

删除镜像

docker rmi -f 镜像ID或者镜像名:TAG
# 删除指定本地镜像
# -f 表示强制删除

# 按镜像ID删除单个镜像:docker rmi 镜像ID
docker rmi c8d03f6b8b91

# 按镜像ID删除多个镜像:docker rmi 镜像ID 镜像ID 镜像ID
docker rmi c8d03f6b8b91 938b57d64674 7faaec683238

# 按镜像ID删除所有镜像,其中 docker images -aq 可以查询到所有镜像的ID
docker rmi $(docker images -aq)

# 删除多个镜像
docker images | grep 'nginx' | awk '{print $3}' | xargs docker rmi

注意:如果通过某个镜像创建了容器,则该镜像无法删除。解决办法:先删除镜像中的容器,再删除该镜像。

导出镜像

docker save mynginx -o /exp/mynginx.tar

docker rmi mynginx # 删除 mynginx 镜像
docker images # 查看镜像,可以看到 mynginx 已经不见了

导入镜像

docker load -i /exp/mynginx.tar
docker images # 查看镜像,可以看到 mynginx 被加载进来了

获取元信息:

docker inspect 镜像ID或者镜像名:TAG
# 获取镜像的元信息,详细信息

容器命令

查看容器

# 查看正在运行的容器
docker ps

# CONTAINER ID    容器 ID
# IMAGE    所属镜像
# COMMAND    启动容器时运行的命令
# CREATED    创建时间
# STATUS    容器状态
# PORTS    端口
# NAMES    容器名称
CONTAINER ID   IMAGE                      COMMAND                  CREATED      STATUS             PORTS                                                  NAMES
abe0cf621fed   redis:6.2.6                "docker-entrypoint.s…"   21 seconds ago   Up 20 seconds   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp
a27fdaf5fbd8   nginx:1.20.1               "/docker-entrypoint.…"   2 days ago   Up 2 days          0.0.0.0:80->80/tcp, :::80->80/tcp                      nginx
7fbcd08dd3a7   mysql:5.7                  "docker-entrypoint.s…"   2 days ago   Up 2 days          0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql
80912a86d5f1   nacos/nacos-server:2.0.3   "bin/docker-startup.…"   2 days ago   Up 2 days          0.0.0.0:8848->8848/tcp, :::8848->8848/tcp              nacos

# 查看所有容器
docker ps -a

# 查看停止的容器
docker ps -f status=exited

# 查看容器的元信息:docker inspect 容器名称或容器ID
docker inspect nginx

创建启动进入退出容器

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

docker run --name 容器名 -i -t -p 主机端口:容器端口 -d -v 主机目录:容器目录:ro 镜像ID或镜像名:TAG
# --name 指定容器名,可自定义,不指定自动命名
# --restart=always 设置容器在退出后的重启策略
# -i 以交互模式运行容器
# -t 分配一个伪终端,即命令行,通常-it组合来使用
# -p 指定映射端口,讲主机端口映射到容器内的端口
# -d 后台运行容器
# -v 指定挂载主机目录到容器目录,默认为rw读写模式,ro表示只读

# 创建容器:docker run -di --name 容器名称 -p 宿主机端口:容器内的映射端口 镜像名称:标签
docker run -di --name nginx -p 80:80 nginx:1.20.1

# 进入正在运行的容器并且开启交互模式终端:docker exec -it 容器名称或容器ID /bin/bash
# /bin/bash是固有写法,作用是因为docker后台必须运行一个进程,否则容器就会退出,在这里表示启动容器后启动 bash。
# 也可以用docker exec在运行中的容器执行命令,比如打开redis客户端 redis-cli
docker exec -it nginx /bin/bash

# 创建并进入容器:docker run -dit --name 容器名称 -p 宿主机端口:容器内的映射端口 镜像名称:标签 /bin/bash
docker run -dit --name nginx -p 80:80 nginx:1.20.1 /bin/bash

# 退出当前容器
exit

停止与启动容器

# 停止容器:docker stop 容器名称或容器ID
docker stop nginx

# 启动容器:docker start 容器名称或容器ID
docker start nginx

# 强制停止容器:docker kill 容器名称或容器ID
docker kill nginx

# 停止所有容器
docker stop $(docker ps -aq)

删除容器

# 删除指定的容器:docker rm 容器名称或容器ID
docker rm nginx

# 删除多个指定的容器:docker rm 容器名称或容器ID 容器名称或容器ID
docker rm nginx mysql

# 删除所有容器
docker rm $(docker ps -aq)

#删除多个容器
docker ps -a | grep "nginx" | awk '{print $1}' | xargs docker rm

文件拷贝

# 宿主机拷贝到容器:docker cp 需要拷贝的文件或目录 容器名称:容器目录
docker cp /home/nginx/conf nginx:/etc/nginx

# 容器拷贝到宿主机:docker cp 容器名称:容器目录 需要拷贝的文件或目录
docker cp nginx:/etc/nginx /home/nginx/conf

目录挂载

我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以通过修改宿主机某个目录的文件从而去影响容器,而且这个操作是双向绑定的,也就是说容器内的操作也会影响到宿主机,实现备份功能。

但是容器被删除的时候,宿主机的内容并不会被删除。如果多个容器挂载同一个目录,其中一个容器被删除,其他容器的内容也不会受到影响。

# 创建容器时添加 -v 参数,格式为:宿主机目录:容器目录
docker run -di --name nginx -p 80:80 -v /home/nginx/conf:/etc/nginx nginx:1.20.1

# 多目录挂载:docker run -di -v 宿主机目录:容器目录 -v 宿主机目录2:容器目录2 镜像名称:标签

提示:目录挂载操作可能会出现权限不足的提示。这是因为 CentOS7 中的安全模块 SELinux 把权限禁掉了,在 docker run 时通过 --privileged=true 给该容器加权限来解决挂载的目录没有权限的问题。

查看容器的 IP 地址

# 查看容器的元信息:docker inspect 容器名称或容器ID
docker inspect nginx

# 直接输出 IP 地址:docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称或容器ID
docker inspect --format='{{.NetworkSettings.IPAddress}}' nginx

查看容器的日志

# 查看当前全部日志:docker logs 容器名称或容器ID
docker logs nginx

# 动态查看日志:docker logs 容器名称或容器ID -f
docker logs nginx -f

应用部署

Nacos

docker pull nacos/nacos-server:2.0.3
# MODE=standalone表示单机启动
docker run -di --name nacos -p 8848:8848 --env MODE=standalone nacos/nacos-server:2.0.3

Nginx

# 下载最新nginx
docker pull nginx
mkdir -p /home/nginx/conf /home/nginx/html /home/nginx/logs
# 先将对应版本默认的配置文件 nginx.conf 上传到 /home/nginx/conf,官网下载地址:http://nginx.org/en/download.html
# 修改配置文件
vi /home/nginx/conf/nginx.conf

启动

docker run --name nginx -p 80:80 -d --net bridge \
-v /home/nginx/html:/usr/share/nginx/html \
-v /home/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /home/nginx/logs:/var/log/nginx \
nginx

# 进入 Nginx 容器
docker exec -it nginx /bin/bash

# 设置开机自启
docker update nginx --restart=always

MySQL

# 这里默认拉取当前 5.7 的最新版本
docker pull mysql:5.7
mkdir -p /home/mysql/conf /home/mysql/data /home/mysql/log

# 新建配置文件
vi /home/mysql/conf/my.conf

配置文件内容

[client]
default-character-set = utf8

[mysql]
default-character-set = utf8

[mysqld]
init_connect=' SET collation_connection = utf8_unicode_ci'
init_connect=' SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve

启动重启

# 启动
docker run -p 3306:3306 --name mysql \
  -v /home/mysql/conf:/etc/mysql/ \
  -v /home/mysql/log:/var/log/mysql \
  -v /mydata/mysql/data:/var/lib/mysql \
  -e MYSQL_ROOT_PASSWORD=root \
  -d mysql:5.7
  
# 进入容器内部
docker exec -it mysql /bin/bash

# 重启mysql
docker restart mysql

# 查看容器内配置文件
docker exec -it mysql /bin/bash
cat /etc/mysql/my.conf

# 设置开机自启
docker update mysql --restart=always

Redis

# 下载最新的 redis
docker pull redis
mkdir -p /home/redis/data
# 先将对应版本默认的配置文件 redis.conf 上传到 /home/redis,官网下载地址:https://download.redis.io/releases/
# 修改配置文件,如:设置密码、持久化等
vi /home/redis/redis.conf
# 持久化 AOF
appendonly yes

# 启动
docker run -p 6379:6379 --name redis \
-v /home/redis/data:/data \
-v /home/redis/conf/redis.conf:/etc/redis/redis.conf \
-d redis redis-server /etc/redis/redis.conf

# 进入 Redis 容器,并使用 redis-cli 命令进行连接
# docker exec -it redis /bin/bash
docker exec -it redis redis-cli
# docker exec -it redis redis-cli -a 123456

# 设置开机自启
docker update redis --restart=always

RabbitMQ

docker pull rabbitmq:3.8.25
docker run -di --name rabbitmq -p 15672:15672 -p 5672:5672 rabbitmq:3.8.25

# 进入 RabbitMQ 容器,并开启管理功能
docker exec -it rabbitmq /bin/bash
rabbitmq-plugins enable rabbitmq_management

Elasticsearch

docker pull elasticsearch:7.14.2
mkdir -p /home/elasticsearch/plugins /home/elasticsearch/data
# 修改虚拟内存区域大小,否则会因为过小而无法启动
sysctl -w vm.max_map_count=262144
# -e 设置参数
docker run -di --name elasticsearch -p 9200:9200 -p 9300:9300 -v /home/elasticsearch/plugins:/usr/share/elasticsearch/plugins -v /home/elasticsearch/data:/usr/share/elasticsearch/data -e "discovery.type=single-node" -e "cluster. elasticsearch:7.14.2

# 进入 Elasticsearch 容器,并安装中文分词器 IKAnalyzer
docker exec -it elasticsearch /bin/bash
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.14.2/elasticsearch-analysis-ik-7.14.2.zip

# 重启 Elasticsearch 容器
docker restart elasticsearch

Logstash

docker pull logstash:7.14.2
mkdir -p /home/logstash
# 拷贝配置文件 logstash.conf 到 /home/logstash 目录下,并修改 output 节点下的 Elasticsearch 连接地址为 es:9200
# output {
#   elasticsearch {
#     hosts => "es:9200"
#     index => "mall-%{type}-%{+YYYY.MM.dd}"
#   }
# }

# -e 设置参数
docker run -di --name logstash -p 4560:4560 -p 4561:4561 -p 4562:4562 -p 4563:4563 -v /home/logstash/logstash.conf:/usr/share/logstash/pipeline/logstash.conf --link elasticsearch:es logstash:7.14.2

# 进入 Logstash 容器,并安装 json_lines 插件
docker exec -it logstash /bin/bash
logstash-plugin install logstash-codec-json_lines

# 重启 Logstash 容器
docker restart logstash

Kibana

docker pull kibana:7.14.2
# -e 设置参数
docker run -di --name kibana -p 5601:5601 --link elasticsearch:es -e "elasticsearch.hosts=http://es:9200" kibana:7.14.2

MongoDB

docker pull mongo:5.0.3
mkdir -p /home/mongo
docker run -di --name mongo -p 27017:27017 -v /home/mongo/db:/data/db mongo:5.0.3

构建镜像

# 使用当前目录的 Dockerfile 创建镜像
docker build -t helloword:1.0.0 .

# 通过 -f Dockerfile 文件的位置创建镜像
docker build -f /home/docker/Dockerfile -t helloword:1.0.0 .

编写 Dockerfile 文件 vi Dockerfile

# 该镜像需要依赖的基础镜像
FROM java:8
# 将当前目录下的 jar 包复制到 docker 容器的 /home/zmall 目录下
ADD zmall-admin-1.0-SNAPSHOT.jar /home/zmall
# 运行过程中创建一个 zmall-admin.jar 文件
RUN bash -c 'touch /home/zmall/zmall-admin.jar'
# 声明服务运行在 8080 端口
EXPOSE 8080
# 指定 docker 容器启动时运行 jar 包
ENTRYPOINT ["java", "-jar","/home/zmall/zmall-admin.jar"]
# 指定维护者的名字
MAINTAINER cxy35
cd /home/zmall

# 构建镜像
docker build -f /home/zmall/Dockerfile -t zmall/zmall-admin:1.0 .

# 创建并启动镜像
docker run -di --name zmall-admin -p 8080:8080 zmall/zmall-admin:1.0

# 进入容器
docker exec -it zmall-admin /bin/bash

# 查看镜像构建历史
docker history zmall/zmall-admin:1.0

参考

https://www.cxy35.com/#/docs/tool/docker


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!