Bootstrap

Docker入门及高级应用

一、初识Docker

1. 项目部署的问题

在这里插入图片描述

2. 什么是Docker

https://www.bilibili.com/video/BV1LQ4y127n4?p=43&spm_id_from=pageDriver
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. Docker与虚拟机

https://www.bilibili.com/video/BV1LQ4y127n4?p=44&spm_id_from=pageDriver
在这里插入图片描述
在这里插入图片描述

4. 镜像和容器

在这里插入图片描述

5. Docker和DockerHub

在这里插入图片描述

6. Docker架构

在这里插入图片描述

7. 安装Docker

7.1 卸载旧版本

yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-selinux \
                  docker-engine-selinux \
                  docker-engine \
                  docker-ce

7.2 安装yum-utils

yum install -y yum-utils
# 或者
yum install -y yum-utils \
	device-mapper-persistent-data \
	lvm2 --skip-broken

7.3 更新本地镜像源

yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新 yum 软件源缓存
yum makecache fast

7.4 安装

yum install -y docker-ce

7.5 启动docker

# 关闭防火墙
systemctl stop firewalld
# 禁止开机去懂
systemctl disable firewalld
# 启动docker 
systemctl enable docker
systemctl start docker
systemctl stop docker
systemctl restart docker
# 查看版本
docker -v

7.6 配置镜像加速

live-restore": true可以去掉

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
    "registry-mirrors": [
		"https://kfwkfulq.mirror.aliyuncs.com",
		"https://2lqq34jg.mirror.aliyuncs.com",
		"https://pee6w651.mirror.aliyuncs.com",
		"https://registry.docker-cn.com",
		"http://hub-mirror.c.163.com",
		"https://registry.docker-cn.com"
	]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

7.7 测试

docker run hello-world

8. ARM架构安装Docker

参考:https://www.cnblogs.com/lwhzj/p/16551039.html

二、Docker的基本操作

镜像相关命令

  • 镜像名称一般分为两部分组成:[respository]:[tag]
  • 在没有指定tag时,默认是lastest,代表是最新版本的镜像

1、镜像操作

在这里插入图片描述
官方仓库 https://hub.docker.com

1.1、示例从DockerHub拉去一个nginx镜像并查看

在这里插入图片描述

1.2、利用docker save将nginx镜像导出磁盘,然后在通过load加载回来

1.2.1、利用docker xx --help命令查看docker save和docker load的语法
docker save --help
1.2.2、使用docker tag 创建新镜像mynginx1.0
1.2.3、使用docker save导出镜像到磁盘
docker save -o nginx.tar nginx:latest
1.2.4、删除原有镜像
docker rmi nginx:latest
1.2.5、导入自定义镜像
docker load -i nginx.tar

2、容器相关命令

在这里插入图片描述

2.1 示例创建一个nginx容器

2.1.1、在dockerHub搜索镜像nginx并运行

访问:官网查看使用命令

# 运行一个容器
docker run --name nginx -p 80:80 -d nginx
# 查看容器是否运行成功
docker ps
# 查看日志
docker logs nginx

命令解读

  • docker run:创建并运行一个容器
  • –name:给容器起一个名字,比如叫做nginx
  • -p:将宿主机端口与容器端口映射,冒号左侧是宿主机端口,右侧是容器端口
  • -d:后台运行容器
  • nginx:镜像名称,例如nginx,没有写tag表示latest

2.2、查看日志

2.2.1、查看日志
docker logs nginx
2.2.2、查看实时持续日志
docker logs -f nginx

docker logs -t -f -tail=100 edevp-app

说明:

  • –since : 指定输出日志开始日期。
  • -f : 查看实时日志
  • -t : 查看日志产生的时间戳
  • -tail=10 : 查看最后的10条日志。
  • container : 容器名

2.3、进入容器

2.3.1、进入容器命令
docker exec -it nginx bash
docker exec -it nginx /bin/bash
# SpringBoot工程
docker exec -it java-app /bin/sh
  • docker exec:进入容器内部,执行一个命令
  • -it:给当前进入的容器创建一个标准输入,输出的终端,允许我们与容器交互
  • nginx:要进入的容器的名称
  • bash:进入容器后执行的命令,bash是一个linux终端交互命令
2.3.2、示例修改nginx的html文件内容

先通过官方文档查看nginx的容器目录
Hosting some simple static content
Alternatively, a simple Dockerfile can be used to generate a new image that includes the necessary content (which is a much cleaner solution than the bind mount above):

FROM nginx
COPY static-html-directory /usr/share/nginx/html

先通过exec进入容器,然后进入nginx的html对应目录

# 进入html目录
cd /usr/share/nginx/html
# 查看内容
cat index.html

修改内容把"Welcome to nginx"替换为"欢迎您"
方法一:vi

vi index.html

方法二:sed

sed -i 's#Welcome to nginx#欢迎您#g' index.html
sed -i 's#<head>#<head><meta charset="utf-8">#g' index.html

2.4、退出容器

exit

2.5、停止容器

docker stop nginx

2.6、启动容器

docker start nginx

2.7、查看容器

# 查看在运行的
docker ps
# 查看所有,包含停止的
docker ps -a

2.8、删除容器

docker rm nginx
# 强制删除
docker rm -f nginx

2.9、示例执行redis的redis-cli命令

docker exec -it redis redis-cli

2.10、容器互联–link

–link可以通过容器名互相通信,容器间共享环境变量。
–link主要用来解决两个容器通过ip地址连接时容器ip地址会变的问题.

1.当新建一个容器时,如果没有显示指定其使用的网络,那么默认会使用bridge网络
2.当一个容器link到另一个容器时,该容器可以通过IP或容器名称访问被link的容器(此时类似于加入相同网络join net),而被link容器可以通过IP访问该容器,但是无法通过容器名称访问
3.当被link的容器被删除时,创建link的容器也无法正常使用
4.如果两个容器被加入到我们手动创建的网络时,那么该网络内的容器相互直接可以通过IP和名称同时访问。

例如:
–link参数连接到了rmqnamesrv容器,并使用了别名namesrv,因此后面再rmqconsole容器中,可以使用namesrv:9876访问rmqnamesrv

docker run -d \
--name rmqconsole \
--net=mynet \
-p 8180:8080 \
--link rmqnamesrv:namesrv \
-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \
-e "JAVA_OPTS=-Drocketmq.namesrv.addr=namesrv:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false" \
-t styletang/rocketmq-console-ng

2.11、跟宿主机时区一致

-v /etc/localtime:/etc/localtime \
-v /etc/timezone:/etc/timezone \

2.12、设置环境变量

docker run --env -e

示例

docker run -e VAR1=value1 --env VAR2=value2 ubuntu
docker run --env VAR1=value1 --env VAR2=value2 ubuntu

You can also use variables that you’ve exported to your local environment:

export VAR1=value1
export VAR2=value2
$ docker run --env VAR1 --env VAR2 ubuntu env | grep VAR
VAR1=value1
VAR2=value2
docker run --env-file

使用文件作为环境变量,.env 文件如下:

# This is a comment
VAR1=value1
VAR2=value2
USER  # which takes the value from the local environment

运行示例:

docker run --env-file .env ubuntu
查看环境变量
docker inspect <CONTAINER-NAME> OR <CONTAINER-ID>

2.13 添加主机名映射

如下映射
config:192.168.1.191
registry:192.168.1.191
rabbitmq:192.168.1.191

docker run -d -p 8989:8989 -p 8080:8080 -e HOST_IP=192.168.1.191 -e CONFIG_SERVICE_PASSWORD=${CONFIG_SERVICE_PASSWORD} --add-host config:192.168.1.191 -e CONFIG_PORT=8888 --add-host registry:192.168.1.191 -e REGISTRY_PORT=8761 --add-host rabbitmq:192.168.1.191 -e RABBITMQ_PORT=5672 --name=monitoring monitoring

2.14 设置启动模式,默认重启

# 创建容器时指定
docker run --restart-always
# 已经启动的容器 docker update --restart=always 容器名
docker update --restart=always kafka-ui

3、数据卷(volume)

3.1、什么是数据卷

容器和数据耦合的问题
在这里插入图片描述
数据卷是一个虚拟目录,指向宿主机文件系统中的某个目录
在这里插入图片描述
数据卷的作用:

将容器与数据分离,解耦合,方便操作容器内数据,保证数据安全

3.2、数据卷基本操作

docker volume [COMMAND]

docker volume命令是数据卷操作,根据命令后跟随的command来确定下一步的操作:

  • create 创建一个volume
  • inspect 显示一个或多个volume的信息
  • ls 列出所有的volume
  • prune 删除未使用的volume
  • rm 删除一个或多个指定的volume

3.3、创建和查看数据卷

需求:创建一个数据卷,并查看数据卷在宿主机的目录位置

3.3.1、创建数据卷
docker volume create html
3.3.2、查看所有数据
docker volume ls
DRIVER    VOLUME NAME
local     de0fd3925a75374dc53808ef97fff74d2a9b2baaf6294244a28a7cc724bdf176
local     f820bf9079ac57b3c8f289d693beeaf4f504be7895cdf6bf361f007a1eaea133
local     html
3.3.3、查看数据卷内容
docker volume inspect html
#可以看到,我们创建的html这个数据卷关联的宿主机目录为/var/lib/docker/volumes/html/_data目录。
[
    {
        "CreatedAt": "2022-04-05T14:14:53+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/html/_data",
        "Name": "html",
        "Options": {},
        "Scope": "local"
    }
]

3.3.4、删除数据卷
# 删除未使用的数据卷
docker volume prune
# 删除指定数据卷
docker volume rm html

3.3.5、数据卷挂载

我们在创建容器时,可以通过 -v 参数来挂载一个数据卷到某个容器内目录,命令格式如下:

docker run \
  --name mn \
  -v html:/root/html \
  -p 8080:80
  nginx \
  

这里的-v就是挂载数据卷的命令:

  • -v html:/root/htm :把html数据卷挂载到容器内的/root/html这个目录中
案例-给nginx挂载数据卷

① 创建容器并挂载数据卷到容器内的HTML目录

docker run --name mn -v html:/usr/share/nginx/html -p 80:80 -d nginx

② 进入html数据卷所在位置,并修改HTML内容

# 查看html数据卷的位置
docker volume inspect html
# 进入该目录
cd /var/lib/docker/volumes/html/_data
# 修改文件
vi index.html

3.4、挂载本地文件和目录

数据卷挂载的方式对比
在这里插入图片描述

容器不仅仅可以挂载数据卷,也可以直接挂载到宿主机目录上。关联关系如下:

带数据卷模式:宿主机目录 --> 数据卷 —> 容器内目录

直接挂载模式:宿主机目录 —> 容器内目录
语法:

目录挂载与数据卷挂载的语法是类似的:

-v [宿主机目录]:[容器内目录]

-v [宿主机文件]:[容器内文件]

实现思路如下:

1)在将课前资料中的mysql.tar文件上传到虚拟机,通过load命令加载为镜像

2)创建目录/tmp/mysql/data

3)创建目录/tmp/mysql/conf,将课前资料提供的hmy.cnf文件上传到/tmp/mysql/conf

4)去DockerHub查阅资料,创建并运行MySQL容器,要求:

① 挂载/tmp/mysql/data到mysql容器内数据存储目录

② 挂载/tmp/mysql/conf/hmy.cnf到mysql容器的配置文件

③ 设置MySQL密码

#创建容器
docker run \
#容器名称自定义为mysql
--name mysql \
#mysql root密码设置为:654321
-e MYSQL_ROOT_PASSWORD=654321 \
#端口映射
-p 3307:3306
#宿主机的/tmp/mysql/conf/hmy.cnf文件挂载到容器的/etc/mysql/conf.d/hmy.cnf文件
-v /tmp/mysql/conf/hmy.cnf:/etc/mysql/conf.d/hmy.cnf \
#宿主机的/tmp/mysql/data目录挂载到容器的/var/lib/mysql目录
-v /tmp/mysql/data:/var/lib/mysql \
#后台运行mysql镜像(版本号5.7.25)
-d mysql:5.7.25

三、Dockerfile自定义镜像

1、镜像结构

镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。
我们以MySQL为例,来看看镜像的组成结构:
![在这里插入图片描述](https://img-blog.csdnimg.cn/7f31bc0a35e14e88824660f499b2763a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQmx1ZWV5ZWRib3k1MjE=,size_20,color_FFFFFF,t_70,g_se,x_16在这里插入图片描述
简单来说,镜像就是在系统函数库、运行环境基础上,添加应用程序文件、配置文件、依赖文件等组合,然后编写好启动脚本打包在一起形成的文件。
我们要构建镜像,其实就是实现上述打包的过程。

2、Dockerfile语法

构建自定义的镜像时,并不需要一个个文件去拷贝,打包。
我们只需要告诉Docker,我们的镜像的组成,需要哪些BaseImage、需要拷贝什么文件、需要安装什么依赖、启动脚本是什么,将来Docker会帮助我们构建镜像。
而描述上述信息的文件就是Dockerfile文件。
Dockerfile就是一个文本文件,其中包含一个个的指令(Instruction),用指令来说明要执行什么操作来构建镜像。每一个指令都会形成一层Layer。
在这里插入图片描述

更新详细语法说明,请参考官网文档: https://docs.docker.com/engine/reference/builder
也可以参考:Dockerfile文件详解

3、构建Java项目

3.1、基于Ubuntu构建Java项目

需求:基于Ubuntu镜像构建一个新镜像,运行一个java项目

  • 步骤1:新建一个空文件夹docker-demo
  • 步骤2:docker-demo.jar文件到docker-demo这个目录
  • 步骤3:jdk8.tar.gz文件到docker-demo这个目录
  • 步骤4:Dockerfile到docker-demo这个目录

Dockerfile其中的内容如下:

# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local
 
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
 
# 安装JDK
RUN cd $JAVA_DIR \
 && tar -xf ./jdk8.tar.gz \
 && mv ./jdk1.8.0_144 ./java8
 
# 配置环境变量
ENV JAVA_HOME=$JAVA_DIR/java8
ENV PATH=$PATH:$JAVA_HOME/bin
 
# 暴露端口
EXPOSE 8090
# 入口,java项目的启动命令
ENTRYPOINT java -jar /tmp/app.jar
  • 步骤5:进入docker-demo目录下
  • 步骤6:运行命令:
docker build -t javaweb:1.0 .

最后访问 http://192.168.150.101:8090/hello/count,其中的ip改成你的虚拟机ip

3.2、基于java8构建Java项目

虽然我们可以基于Ubuntu基础镜像,添加任意自己需要的安装包,构建镜像,但是却比较麻烦。所以大多数情况下,我们都可以在一些安装了部分软件的基础镜像上做改造。

例如,构建java项目的镜像,可以在已经准备了JDK的基础镜像基础上构建。

需求:基于java:8-alpine镜像,将一个Java项目构建为镜像

实现思路如下:

① 新建一个空的目录,然后在目录中新建一个文件,命名为Dockerfile

② 拷贝课前资料提供的docker-demo.jar到这个目录中

③ 编写Dockerfile文件:

a )基于java:8-alpine作为基础镜像

b )将app.jar拷贝到镜像中

c )暴露端口

d )编写入口ENTRYPOINT

内容如下:

FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
EXPOSE 8090
ENTRYPOINT java -jar /tmp/app.jar
# 可以指定yml文件
# ENTRYPOINT java -Dfile.encoding=utf-8 -jar /tmp/app.jar --spring.profiles.active=prod

④ 使用docker build命令构建镜像
如果不写tag则默认latest

docker build -t edevp-user:0.0.1 .
# 查看
docker images

⑤ 使用docker run创建容器并运行

docker run -d -P --name edevp-user edevp-user:0.0.1 

⑥ 通过Docker run命令定义Spring Profile
可以将spring profile作为环境变量传递给docker run命令,使用 -e 标记。
例如 -e “SPRING_PROFILES_ACTIVE=dev”会将dev profile传递给Docker容器

docker run -d -p 8080:8080 -e "SPRING_PROFILES_ACTIVE=dev" --name edevp-user edevp-user:0.0.1 

小结:

Dockerfile的本质是一个文件,通过指令描述镜像的构建过程

Dockerfile的第一行必须是FROM,从一个基础镜像来构建

基础镜像可以是基本操作系统,如Ubuntu。也可以是其他人制作好的镜像,例如:java:8-alpine

3.4、基于Portainer构建Java项目

3.4.1、新建文件夹

mkdir edevp-gateway

3.4.2、组装文件

cd edevp-gateway
touch Dockerfile
# 拷贝之前的文件
# 上传app.jar

在这里插入图片描述

3.4.3、打包tar

tar -cf edevp-gateway.tar *

3.4.4、在Portainer中build

在这里插入图片描述

在这里插入图片描述

四、Docekr-Compose

1、Docker-Compose简介

官方文档
Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。 Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡。 Docker-Compose的工程配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。 使用一个Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。 Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。 Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
在这里插入图片描述

2、Docker-Compose安装

2.1、 从源代码下载

  • Github源
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
# 给docker-compose添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose

  • Daocloud源
curl -L https://get.daocloud.io/docker/compose/releases/download/1.22.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
  • 给docker-compose添加可执行权限
sudo chmod +x /usr/local/bin/docker-compose

2.2、 通过pip安装

ubuntu安装

# 查看linux内核
uname -a
# 安装
apt-get install python-pip
# python3
apt-get install python3-pip
apt-get -y install docker-compose

红帽系Linux使用以下命令安装

yum -y install python-pip
yum -y install docker-compose

centos7.9安装

yum install epel-release
yum install python3-pip 
pip3 install --upgrade pip 
pip3 install docker-compose  
这里会报错:ModuleNotFoundError: No module named 'setuptools_rust'
解决方法:pip3 install -U pip setuptools
docker-compose --version
# 查看安装的版本
docker-compose -v
# docker-compose version 1.25.0, build unknown

2.3、 安装Compose命令补全工具

按照上文讲解,我们已经成功地安装完Docker Compose。但是,我们输入docker-compose 命令,按下TAB键,发现此时Compose并没有给我们该命令的提示,那么如何让命令给我们提示呢?我们需要安装Compose命令补全工具。Compose命令补全在Bash和Zsh下的安装方式不同,由于笔者是使用CentOS 7进行讲解的,而CentOS 7默认使用Bash,故而本文只讲解命令补全在Bash下的安装,其他Shell以及其他系统上的安装,请查看Docker的官方文档:https://docs.docker.com/compose/completion/

curl -L https://raw.githubusercontent.com/docker/compose/$(docker-compose version --short)/contrib/completion/bash/docker-compose > /etc/bash_completion.d/docker-compose

如果命令失败,则修改hosts

echo "199.232.68.133 raw.githubusercontent.com" >> /etc/hosts

再次尝试,发现可以正常列出docker的子命令,示例如下:

[root@docker ~]# docker  (docker + 空格 + 连续按2次Tab键)
attach    container  engine    history   inspect   logs      port     restart   search    stats    top      volume
build     context    events    image     kill      network   ps       rm        secret    stop     trust    wait
builder   cp         exec      images    load      node      pull     rmi       service   swarm    unpause    
commit    create     export    import    login     pause     push     run       stack     system   update     
config    diff       help      info      logout    plugin    rename   save      start     tag      version   

3、Docker-Compose卸载

apt-get remove docker-compose

部署容器-up

# 前台启动
docker-compose up
# 后台启动
docker-compose up -d
# -f 指定使用的 Compose 模板文件,默认为 docker-compose.yml,可以多次指定,指定多个 yml
docker-compose -f docker-compose.yml up -d

日志日志-logs

docker-compose logs查看服务容器的输出日志。默认情况下,docker-compose将对不同的服务输出使用不同的颜色来区分。可以通过--no-color来关闭颜色。

# 输出日志,不同的服务输出使用不同的颜色来区分
docker-compose logs
# 跟踪日志输出
docker-compose logs -f
# 关闭颜色
docker-compose logs --no-color

部署容器-ps

docker-compose ps列出工程中所有服务的容器。

# 列出工程中所有服务的容器
docker-compose ps
# 列出工程中指定服务的容器
docker-compose ps nginx

在指定容器上执行一个命令-run

docker-compose run在指定服务容器上执行一个命令。

# 在工程中指定服务的容器上执行 echo "helloworld"
docker-compose run nginx echo "helloworld"

进入服务容器-exec

docker-compose exec进入服务容器。

# 进入工程中指定服务的容器
docker-compose exec nginx bash
# 当一个服务拥有多个容器时,可通过 --index 参数进入到该服务下的任何容器
docker-compose exec --index=1 nginx bash

暂停服务容器-pause

docker-compose pausedocker-compose pause暂停服务容器

# 暂停工程中所有服务的容器
docker-compose pause
# 暂停工程中指定服务的容器
docker-compose pause nginx

恢复服务容器-unpause

docker-compose unpause恢复服务容器。

# 在工程中指定服务的容器上执行 echo "helloworld"
docker-compose run nginx echo "helloworld"

启动服务容器-start

docker-compose start启动服务容器。

# 启动工程中所有服务的容器
docker-compose start
# 启动工程中指定服务的容器
docker-compose start nginx

停止服务容器-stop

docker-compose stop停止服务容器。

# 在工程中指定服务的容器上执行 echo "helloworld"
docker-compose run nginx echo "helloworld"

停止指定服务容器-kill

docker-compose killdocker-compose kill通过发送SIGKILL信号停止指定服务的容器。

# 通过发送 SIGKILL 信号停止工程中指定服务的容器
docker-compose kill nginx

删除服务(停止状态)容器-rm

docker-compose rm 删除服务(停止状态)容器。

# 删除所有(停止状态)服务的容器
docker-compose rm
# 先停止所有服务的容器,再删除所有服务的容器
docker-compose rm -s
# 不询问是否删除,直接删除
docker-compose rm -f
# 删除服务容器挂载的数据卷
docker-compose rm -v
# 删除工程中指定服务的容器
docker-compose rm -sv nginx

停止并删除所有服务的容器-down

停止并删除所有服务的容器、网络、镜像、数据卷

# 停止并删除工程中所有服务的容器、网络
docker-compose stop
# 停止并删除工程中所有服务的容器、网络、镜像
docker-compose down --rmi all
# 停止并删除工程中所有服务的容器、网络、数据卷
docker-compose down -v

打印服务容器-images

docker-compose images打印服务容器所对应的镜像。

# 打印所有服务的容器所对应的镜像
docker-compose images
# 打印指定服务的容器所对应的镜像
docker-compose images nginx

打印容器的端口映射的宿主机端口-port

docker-compose port打印指定服务容器的某个端口所映射的宿主机端口。

docker-compose port nginx 80

显示正在运行的进程-top

docker-compose top显示正在运行的进程。

# 显示工程中所有服务的容器正在运行的进程
docker-compose top
# 显示工程中指定服务的容器正在运行的进程
docker-compose top nginx

## 指定时区

    environment:
      TZ: Asia/Shanghai
```yaml
apollo-db:
    image: mysql:5.7
    container_name: apollo-db
    environment:
      TZ: Asia/Shanghai
# 五、DockerCompose部署微服务
## 1、新建文件夹

```bash
mkdir cloud-demo
cd cloud-demo
mkdir edevp-gateway edevp-order edevp-user

2、在每个服务目录定义Dockerfile

FROM java:8-alpine
COPY ./app.jar /tmp/app.jar
ENTRYPOINT java -jar /tmp/app.jar

3、修改自己的项目,将数据库、nacos地址都命名为docker-compose中的服务名

spring:
  application:
    name: @artifactId@
  profiles:
    active: @profiles.active@

  cloud:
    nacos:
      discovery: #服务注册与发现
        server-addr: ${NACOS_HOST:nacos}:${NACOS_PORT:8848} #nacos地址
        username: dev
        password: 123456
        namespace: edevp-demo #指定命名空间 可以删掉namespace不写默认public

      #配置文件组成 : 通俗点 服务名称-指定环境.后缀名称  name-active.file-extension
      config: #动态配置
        server-addr: ${spring.cloud.nacos.discovery.server-addr} #nacos地址
        username: dev
        password: 123456
        file-extension: yml #配置文件类型  非常重要后缀一定要一致 xxx.yml
        namespace: edevp-demo #指定命名空间 可以删掉namespace不写默认public
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

4、 通过maven将每个微服务都打包成app.jar

可以在各自微服务的pom.xml中指定打包之后的名字

<build>
        <finalName>app</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>

    </build>

5、 分别拷贝每个微服务文件到对应文件夹

6、创建docker网络

6.1、通过portainer.io创建

在这里插入图片描述

6.2、通过命令创建

docker network create mynet
# 或者指定网段
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
# 查看
docker network ls
# 查看自定义网络
docker network inspect mynet

6.3、把nacos、redis、mysql等中间件加入到自定义网络mynet

方法一:命令方式

docker network connect mynet nacos
# 如果容器已创建好但是之前没有指定自己的网络,则使用下面命令修改:
docker network connect --alias mysql mynet mysql
docker network connect --alias nacos mynet nacos 
docker network connect --alias redis mynet redis

方法二:portainer.io
点击某个容器进入编辑页面加入
在这里插入图片描述

7、新建docker-compose.yml

在cloud-demo目录下新建

version: '3.2'


#networks:
#  mynet:
#    driver: bridge

services:

  edevp-user:
    #    image: registry.cn-shanghai.aliyuncs.com/demo-store/demo_online:demo-usercenter-v1.0
    container_name: edevp-user
    build: ./edevp-user
    environment:
      TZ: Asia/Shanghai
  #    ports:
  #      - 8204:8204
    networks:
      - mynet

  edevp-order:
    #    image: registry.cn-shanghai.aliyuncs.com/demo-store/demo_online:demo-usercenter-v1.0
    container_name: edevp-order
    build: ./edevp-order
    environment:
      TZ: Asia/Shanghai
    networks:
      - mynet

  edevp-gateway:
    container_name: edevp-gateway
    build: ./edevp-gateway
    environment:
      TZ: Asia/Shanghai
    ports:
      - 8888:8888
    networks:
      - mynet


networks:
  mynet:
    external: true

注意指定自定义网络mynet,并且由于使用外部网络,所以需要设置external:true

8、构建

# 在cloud-demo目录下执行
docker-compose up -d

8、测试

curl http://127.0.0.1:8888/orders/1?authorization=admin

六、Docker镜像仓库

docker镜像仓库(repository)是集中存放镜像的地方。方便与后续的镜像拉取与上传,便于对镜像的集中管理。镜像仓库一般可分为Docker Hub公共中央仓库和个人或者公司使用的私有仓库,私有仓库如果是个人使用则可以直接使用docker自带的registry私有仓库,如果是企业级使用则可以搭建Harbor镜像私有仓库。
镜像仓库有公有和私有两种
公有仓库:例如官方DockerHub,国内有网易云镜像仓库,阿里云镜像仓库,DaoCloud镜像服务等
私有仓库:DockerRegistry(个人)、harbor(企业)

6.1、Docker Registry

官网https://hub.docker.com/_/registry

6.1.1、简化版

docker run -d -p 5000:5000 --restart always -v registry-data:/var/lib/registry --name registry registry:2

6.1.2、带有图形化界面

6.1.2.1、新建文件夹registry
mkdir /usr/local/docker/registry
6.1.2.2、新建docker-compose.yml
cd /usr/local/docker/registry
touch docker-compose.yml

不指定网路

version: '3.0'
services:
  registry:
    image: registry
    volumes:
      - ./registry-data:/var/lib/registry
  ui:
    image: joxit/docker-registry-ui:static
    ports:
      - 8080:80
    environment:
      - REGISTRY_TITLE=图形化私有仓库
      - REGISTRY_URL=http://registry:5000
    depends_on:
      - registry

#可以指定网络mynet,也可以去掉

version: '3.0'
services:
  registry:
    image: registry
    volumes:
      - ./registry-data:/var/lib/registry
    networks:
      - mynet
  ui:
    image: joxit/docker-registry-ui:static
    ports:
      - 8080:80
    environment:
      - REGISTRY_TITLE=图形化私有仓库
      - REGISTRY_URL=http://registry:5000
    depends_on:
      - registry
    networks:
      - mynet
networks:
  mynet:
    external: true

依赖depends_on表示ui服务启动依赖于registry

6.1.2.3、配置Docker的受信任地址

我们私服采用的是http协议,默认不被Docker新人,所有需要做一个配置:
由于我们使用了ui图形工具,所以端口5000改为8080

# 打开要修改的文件
vim /etc/docker/daemon.json
# 加上下面这一句,这里的“your-server-ip”请换为你的服务器的外网IP地址:

{
"insecure-registries" : [ "your-server-ip:5000" ]
}
# 由于我们使用了ui图形工具,所以端口是8080
# 效果如下:
{
	"registry-mirrors": [
		"https://kfwkfulq.mirror.aliyuncs.com",
		"https://2lqq34jg.mirror.aliyuncs.com",
		"https://pee6w651.mirror.aliyuncs.com",
		"https://registry.docker-cn.com",
		"http://hub-mirror.c.163.com",
		"https://registry.docker-cn.com"
	],
	"insecure-registries": ["http://192.168.0.44:8080"]
}
# 重新加载
systemctl daemon-reload
# 重启docker
systemctl restart docker
6.1.2.4、构建
# cd /usr/local/docker/registry
docker-compose up -d

访问:http://192.168.0.44:8080/
在这里插入图片描述

6.1.2.5、重启
docker start registry_registry_1
docker start registry_ui_1
6.1.2.6、推送到镜像仓库

注意端口,如果安装了图形界面8080,则5000改为8080

# 重新tag本地镜像,
docker tag your-image-name:tagname your-server-ip:5000/your-image-name:tagname
# 示例表示把edevp-user:latest重命名为192.168.0.44:5000/edevp-user:0.0.1
docker tag edevp-user:latest 192.168.0.44:5000/edevp-user:0.0.1
# 示例nginx
docker tag nginx:latest 192.168.0.44:8080/nginx:1.0

# 推送

# 最后,开始正式上传镜像到服务端镜像仓库
docker push your-registry-server-ip:8080/your-image-name:tagname
# 示例
docker push 192.168.0.44:8080/edevp-user:0.0.1# 示例
docker push 192.168.0.44:8080/nginx:1.0

推送之后可以在界面看到如下:
在这里插入图片描述

6.1.2.7、拉取
docker pull 192.168.0.44:8080/nginx:1.0

6.2、Harbor企业级镜像仓库

6.2.1、概述

harbor意为港湾, 很贴合它的作用

github地址: https://github.com/goharbor/harbor

记得以前是在vmware下, 现在地址转到goharbor下了

官方的定义是企业级私有Registry服务器, 实际内部也是依靠docker registry

那么它与registry相比, 一定提供了很多企业级的特性, 例如:

  • 提供良好的Web界面
  • 提供良好的安全机制, 包括角色, 权限控制, 日志等
  • 支持水平扩展
  • 传输优化, 因为镜像的分层机制, 所以每次传输并非全量, 从而提升速度
    搭建

环境准备

在安装harbor之前, 需要docker环境, 除此还需要docker-compose, 不说了

6.2.2、安装

参考安装教程https://www.cnblogs.com/chinda/p/12776675.html

6.2.2.1、下载

在github release中查看需要安装的版本, 这里我用当前最新的v1.7.5

文档中有两种安装方式: offline和online, 也就是在线和离线

  • online: 在线方式会下载一个很小的tar包, 里面只有docker-compose.yml和启动脚本, 会在启动安装时在线拉取镜像
  • offline: 下载一个大概500多M的tar包, 里面包括了镜像文件, 所以安装时会快
    我的浏览器设置了代理, 所以选择offline的离线包, 再上传放到docker环境的主机上
    下载官网:https://github.com/goharbor/harbor/releases
    在这里插入图片描述

下载地址:

# 1、在线安装包
$ wget https://github.com/vmware/harbor/releases/download/v2.4.2/harbor-online-installer-v2.4.2.tgz
tar xvf harbor-online-installer-v2.4.2.tgz
# 2、离线安装包
$ wget https://github.com/vmware/harbor/releases/download/v2.4.2/harbor-offline-installer-v2.4.2.tgz
$ tar xvf harbor-offline-installer-v2.4.2.tgz

解压之后的结构

root@sony-HP-Notebook:/usr/local/docker/harbor/harbor# tree
.
├── common.sh
├── harbor.v2.4.2.tar.gz
├── harbor.yml.tmpl
├── install.sh
├── LICENSE
└── prepare

0 directories, 6 files

6.2.2.2、配置
# 备份一份配置文件
cp harbor.yml.tmpl harbor.yml
vim harbor.yml

修改如下几个位置


# 注释中也说了, 不要设置成localhost和127.0.0.1阿
hostname = hub.edevp.cn
https:
  port: 443
  certificate: /usr/local/docker/harbor/cert/hub.edevp.cn.crt
  private_key: /usr/local/docker/harbor/cert/hub.edevp.cn.key
# 修改admin默认的登录密码
harbor_admin_password = 123456
6.2.2.3、修改hosts映射
vim /etc/hosts
# 加入如下
192.168.0.44	hub.edevp.cn
6.2.2.4、生成SSL证书支持https访问
生成机构颁发的证书
  • 生成CA证书私钥
cd /usr/local/docker/harbor/cert
openssl genrsa -out ca.key 4096
  • 生成CA证书
openssl req -x509 -new -nodes -sha512 -days 3650 \
 -subj "/C=CN/ST=Beijing/L=Beijing/O=chinda/OU=chinda/CN=hub.edevp.cn" \
 -key ca.key \
 -out ca.crt
生成服务器证书

证书通常包含一个.crt文件和一个.key文件。

  • 生成私钥
openssl genrsa -out hub.edevp.cn.key 4096
  • 生成证书签名(CSR)
openssl req -sha512 -new \
    -subj "/C=CN/ST=Beijing/L=Beijing/O=chinda/OU=chinda/CN=hub.edevp.cn" \
    -key hub.edevp.cn.key \
    -out hub.edevp.cn.csr
  • 生成x509 v3扩展文件
cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=hub.edevp.cn
DNS.2=edevp
DNS.3=hub
EOF
  • 使用v3.ext文件为Harbor主机生成证书

将chinda.com`CRS和CRT文件名中的替换为Harbor主机名。

openssl x509 -req -sha512 -days 3650 \
    -extfile v3.ext \
    -CA ca.crt -CAkey ca.key -CAcreateserial \
    -in hub.edevp.cn.csr \
    -out hub.edevp.cn.crt
提供证书给Harbor和Docker

生成ca.crthub.edevp.cn.crthub.edevp.cn.key文件后,必须将它们提供给Harbor和Docker和重新配置使用它们的Harbor。首先创建存放他们的文件夹。

  • 将服务器证书和密钥复制到Harbor主机的cert文件夹中。
# 我们本身就在当前文件夹
# cp chinda.com.crt /data/cert/
# cp chinda.com.key /data/cert/
# chmod a+x  /data/cert/
chmod a+x *
  • 转换hub.edevp.cn.crt为hub.edevp.cn.cert,供Docker使用。

Docker守护程序将.crt文件解释为CA证书,并将.cert文件解释为客户端证书。

openssl x509 -inform PEM -in hub.edevp.cn.crt -out hub.edevp.cn.cert
  • 将服务器证书,密钥和CA文件复制到Harbor主机上的Docker 证书文件夹中。首先创建适当的文件夹。
mkdir /etc/docker/certs.d/hub.edevp.cn
cp hub.edevp.cn.cert /etc/docker/certs.d/hub.edevp.cn/
cp hub.edevp.cn.key /etc/docker/certs.d/hub.edevp.cn/
cp ca.crt /etc/docker/certs.d/hub.edevp.cn/
  • 重启Docker引擎
systemctl restart docker
6.2.2.5、运行脚本安装
cd /usr/local/harbor/harbor
./install.sh 

6.2.3、访问

https://192.168.0.44/harbor/projects
或者
https://hub.edevp.cn/harbor/projects
admin/123456
在这里插入图片描述

6.2.4、docker登录

docker login https://hub.edevp.cn

6.2.5、操作

# 查看执行状态。注意,要在项目下执行此命令,不然会抛出异常
docker-compose ps
# 停止/移除存在的实例
docker-compose down -v
# 重启harbor
docker-compose up -d

6.2.6、推送镜像的Docker命令

# 在项目中标记镜像:
docker tag SOURCE_IMAGE[:TAG] chinda.com/library/IMAGE[:TAG]
# 示例
docker tag nginx:latest hub.edevp.cn/library/nginx:1.0
# 推送镜像到当前项目:
docker push chinda.com/library/IMAGE[:TAG]
docker push hub.edevp.cn/library/nginx:1.0

效果:
在这里插入图片描述

6.2.7、鉴权失败401 Unauthorized

[root@harbor harbor]# docker login https://chinda.com
Authenticating with existing credentials...
Login did not succeed, error: Error response from daemon: login attempt to https://chinda.com/v2/ failed with status: 401 Unauthorized
Username (admin): admin
Password: 
Error response from daemon: login attempt to https://chinda.com/v2/ failed with status: 401 Unauthorized

解决方案

docker-compose down -v
docker-compose up -d
;