文章目录
Docker引擎的安装
安装Docker需要的依赖gcc gcc-c++
yum -y install gcc
yum -y install gcc-c++
因为我之前已经安装了,所以现在提示"Nothing to do"
[root@localhost ~]# yum -y install gcc
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Package gcc-4.8.5-44.el7.x86_64 already installed and latest version
Nothing to do
[root@localhost ~]# yum -y install gcc-c++
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Package gcc-c++-4.8.5-44.el7.x86_64 already installed and latest version
Nothing to do
非root用户需要使用sudo提权
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
安装Docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
查看docker版本
docker version
[root@localhost ~]# docker version
Client: Docker Engine - Community
Version: 26.0.0
API version: 1.45
Go version: go1.21.8
Git commit: 2ae903e
Built: Wed Mar 20 15:21:09 2024
OS/Arch: linux/amd64
Context: default
Server: Docker Engine - Community
Engine:
Version: 26.0.0
API version: 1.45 (minimum version 1.24)
Go version: go1.21.8
Git commit: 8b79278
Built: Wed Mar 20 15:20:06 2024
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.28
GitCommit: ae07eda36dd25f8a1b98dfbf587313b99c0190bb
runc:
Version: 1.1.12
GitCommit: v1.1.12-0-g51d5e94
docker-init:
Version: 0.19.0
GitCommit: de40ad0
运行hello-world
docker run hello-world
[root@localhost ~]# docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
c1ec31eb5944: Pull complete
Digest: sha256:53641cd209a4fecfc68e21a99871ce8c6920b2e7502df0a20671c6fccc73a7c6
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
Docker比vm虚拟机快
为什么Docker会比vm虚拟机快
1.docker有着比虚拟机更少的抽象层
由于docker不需要Hypervisor(虚拟机)实现硬件资源虚拟化,
运行在docker容器上的程序直接使用的都是实际物理机的硬件资源,因此在cpu、内存利用率上docker将会在效率上有明显优势。
2.docker利用的是宿主机的内核,而不是需要加载操作系统os内核
当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核。
Docker常用命令
Docker启动管理命令
systemctl start docker
systemctl stop docker
systemctl status docker
systemctl restart docker
systemctl enable docker
docker info
docker --help
docker command(具体命令) --help
镜像命令
docker images
docker images #列出本地主机上的镜像
[root@localhost ~]# docker images
REPOSITORY(表示镜像的仓库源) TAG(镜像的标签版本号) IMAGE ID(镜像ID) CREATED(镜像创建时间) SIZE(镜像大小)
hello-world latest d2c94e258dcb 11 months ago 13.3kB
docker search
docker search 镜像名称
docker search redis
[root@localhost ~]# docker search redis
NAME DESCRIPTION STARS OFFICIAL
redis Redis is an open source key-value store that… 12764 [OK]
redislabs/redisearch Redis With the RedisSearch module pre-loaded… 63
redislabs/redisinsight RedisInsight - The GUI for Redis 101
redis/redis-stack-server redis-stack-server installs a Redis server w… 72
redis/redis-stack redis-stack installs a Redis server with add… 103
redislabs/rebloom A probablistic datatypes module for Redis 27
redislabs/redis Clustered in-memory database engine compatib… 40
......
name 镜像名称
DESCRIPTION 镜像说明
STATRS 点赞数量
OFFICIAL 是否官方认证
docker search --limit 5 redis #搜索前五名
docker pull
下载镜像
docker pull 镜像名字[:TAG] #没有TAG就是最新版
docker system df
查看镜像/容器/数据卷所占的空间
docker rmi
删除镜像
docker rmi -f 镜像ID #删除单个
docker rmi -f 镜像名1:TAG 镜像名2:TAG #删除多个
docker rmi -f$(docker images -qa) #删除全部
docker rm
删除下图中NAMES为redis的容器
docker rm redis
容器命令
[root@localhost ~]# docker run --help
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Create and run a new container from an image
Aliases:
docker container run, docker run
Options:
-i, --interactive Keep STDIN open even if not attached
-t, --tty Allocate a pseudo-TTY
-d, --detach Run container in background and print container ID
redis前台交互式启动
前台启动很容易被意外终止,窗口一关就没了
docker run -it redis:6.0.8
redis后台守护进程启动
docker run -d redis:6.0.8
查看容器内运行的进程
Nginx容器运行
保存拉取好的nginx镜像
删除nginx镜像,通过上一步保存好的nginx.tar包再将nginx加载回来
创建nginx容器
docker run -d --name nginx -p 80:80 nginx
[root@localhost ~]# docker run -d --name nginx -p 80:80 nginx
c37c23e22fcb0001e16f0da7e4d23f7787673f1e222e788826ea843c55d26437
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c37c23e22fcb nginx "/docker-entrypoint.…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp, :::80->80/tcp nginx
停掉nginx容器
docker stop nginx
启动nginx容器
docker start nginx
查看nginx日志
docker logs nginx
docker logs -f nginx #持续刷新日志
进入nginx容器内部
docker exec -it nginx bash
ubuntu交互式运行
当我们直接使用docker run(不加任何参数)运行某个容器,使用ps命令查看容器状态时,STATUS显示的是‘Exited’,表示已经退出了。当我们希望有交互式的命令输入时,需要使用到‘-it’参数
docker run -it --name myubuntu2 ubuntu /bin/bash
交互式时,容器的状态是’Up’
tomcat交互式运行
docker run --name mytomcat2 -it tomcat:8.5.49
当运行完以上命令后,以下为截取的部分tomcat启动运行日志,可以看到tomcat启动成功了。
[root@localhost ~]# docker run --name mytomcat2 -it tomcat:8.5.49
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/openjdk-8
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
.......
ProtocolHandler ["http-nio-8080"]
11-Apr-2024 07:33:02.042 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
11-Apr-2024 07:33:02.058 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 571 ms
查看容器状态时,可以看到COMMAND为“catalina.sh run”, 此命令可以参考tomcat的Dockerfile
既然tomcat都启动成功了,那tomcat就可以访问了吗,此时我们访问下这个主机的8080端口试一下,
哦NO,汤姆小猫并没有出来,此时你需要对外暴露访问端口。
对外暴露访问端口
专用术语称之为端口映射,将宿主机的8080端口映射为8081,也就是对外我们访问8081端口就等于访问宿主机的8080端口。
docker run --name mytomcat3 -it -p 8081:8080 tomcat:8.5.49
-p, --publish list Publish a container's port(s) to the host
# -p参数用于指定发布端口
[root@localhost ~]# docker run --name mytomcat3 -it -p 8081:8080 tomcat:8.5.49
Using CATALINA_BASE: /usr/local/tomcat
Using CATALINA_HOME: /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME: /usr/local/openjdk-8
Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
11-Apr-2024 07:45:24.267 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name: Apache Tomcat/8.5.49
11-Apr-2024 07:45:24.269 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built: Nov 17 2019 18:45:30 UTC
11-Apr-2024 07:45:24.269 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 8.5.49.0
11-Apr-2024 07:45:24.269 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name: Linux
11-Apr-2024 07:45:24.269 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version: 3.10.0-1160.el7.x86_64
11-Apr-2024 07:45:24.270 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture: amd64
11-Apr-2024 07:45:24.270 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home: /usr/local/openjdk-8/jre
11-Apr-2024 07:45:24.270 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version: 1.8.0_232-b09
11-Apr-2024 07:45:24.270 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor: Oracle Corporation
11-Apr-2024 07:45:24.270 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE: /usr/local/tomcat
11-Apr-2024 07:45:24.270 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME: /usr/local/tomcat
......
11-Apr-2024 07:45:24.990 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory [/usr/local/tomcat/webapps/manager] has finished in [16] ms
11-Apr-2024 07:45:24.998 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
11-Apr-2024 07:45:25.009 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["ajp-nio-8009"]
11-Apr-2024 07:45:25.013 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 594 ms
此时我们访问8081端口:
噢耶,Tomcat小猫咪出来了。
Dockerfile
Dockerfile 是用于构建 Docker 镜像的脚本文件,由一系列指令构成。通过 docker build命令构建镜像时,Dockerfile 中的指令会由上而下依次执行,每条指令都将会构建出一个镜像,这就是镜像的分层。因此指令越多,层次就越多,创建的镜像就越多,效率就越低。所以在定义 Dockerfile 时,能用一个指令完成的动作就不要分为两条。
对于 Dockerfile 的指令,需要注意以下几点:
指令是大小写不敏感的,但惯例是写为全大写。
指令后至少会携带一个参数。
"#"号开头的为注释行
FROM:指定基础镜像
【语法】FROM <image>[:<tag>]
【解析】用于指定基础镜像,且必须是第一条指令;若省略了tag,则默认为 latest。
LABEL:指定镜像元数据
【语法】LABEL <key>=<value> <key>=<value> „„
【解析】LABEL 指令中可以以键值对的方式包含任意镜像的元数据信息,用于替代MAINTAINER 指令。
通过 docker inspect 可查看到 LABEL 与 MAINTAINER 的内容。
ENV:设置环境变量
【语法1】ENV <key> <value>
【解析】用于指定环境变量,这些环境变量,后续可以被 RUN 指令使用,容器运行起来之后,也可以在容器中获取这些环境变量。
【语法2】ENV <key1>=<value1> <key2>=<value2> ...
【解析】可以设置多个变量,每个变量为一对<key>=<value>指定。
COPY:复制文本
【说明】功能与 ADD 指令相同,只不过 src 不能是 URL。若 src 为压缩文件,复制到容器后不会自动解压。
ADD:复制和解包文件
【语法 1】ADD <src> <dest>
【语法 2】ADD ["<src>", "<dest>"] # 路径中存在空格时使用双引号引起来
【解析】该指令将复制当前宿主机中指定文件 src 到容器中的指定目录 dest 中。src 可以是宿主机中的绝对路径,也可以时相对路径。
但相对路径是相对于 docker build 命令所指定的路径的。src 指定的文件可以是一个压缩文件,压缩文件复制到容器后会自动解为 目录;
src 也可以是一个 URL,此时的 ADD 指令相当于 wget 命令;
src 最好不要是目录,其会将该目录中所有内容复制到容器的指定目录中。
dest 是一个绝对路径,其最后面的路径必须要加上斜杠,否则系统会将最后的目录名称当做是文件名的。
WORKDIR:指定工作目录
【语法】WORKDIR path
【解析】容器打开后默认进入的目录,一般在后续的 RUN、CMD、ENTRYPOINT、ADD 等指令中会引用该目录。
可以设置多个 WORKDIR 指令。后续 WORKDIR 指令若用的是相对路径,
则会基于之前 WORKDIR 指令指定的路径。
在使用 docker run 运行容器时,可以通过-w 参数覆盖构建时所设置的工作目录。
RUN:执行shell命令
【语法1】RUN <command>
【解析】这里的<command>就是 shell 命令。docker build 执行过程中,会使用 shell 运行指定的 command。
【语法2】RUN ["EXECUTABLE","PARAM1","PARAM2", ...]
【解析】在 docker build 执行过程中,会调用第一个参数"EXECUTABLE"指定的应用程序运行,
并使用后面第二、三等参数作为应用程序的运行参数。
CMD: 容器启动命令
【语法1】CMD ["EXECUTABLE","PARAM1","PARAM2", ...]
【解析】在容器启动后,即在执行完 docker run 后会立即调用执行"EXECUTABLE"指定的可执行文件,并使用后面第二、第三...等参数作为应用程序的运行参数。
【语法 2】CMD command param1 param2, ...
【解析】这里的 command 就是 shell 命令。在容器启动后会立即运行指定的 shell 命令。
【语法 3】CMD ["PARAM1","PARAM2", ...]
【解析】提供给 ENTERYPOINT 的默认参数。
run和cmd的区别:run是构建镜像时的命令,而cmd则是启动容器时的命令
ENTRYPOINT:入口点,功能类似于CMD,配置容器启动后执行的命令以及参数
【语法1】ENTRYPOINT ["EXECUTABLE","PARAM1","PARAM2", ...]
【解析】在容器启动过程中,即在执行 docker run 时,会调用执行"EXECUTABLE"指定的应用程序,并使用后面第二、第三...等参数作为应用程序的运行参数。
【语法2】ENTRYPOINT command param1 param2, ...
【解析】这里的 command 就是 shell 命令。在容器启动过程中,即在执行 docker run 时,会运行指定的 shell 命令。
EXPOSE: 暴露端口
【语法】EXPOSE <port> [<port>...]
【解析】指定容器准备对外暴露的端口号,但该端口号并不会真正的对外暴露。若要真正暴露,则需要在执行 docker run 命令时使用-p(小 p)来指定说要真正暴露出的端口号。
ONBUILD:子镜像引用父镜像的指令
【语法】ONBUILD [INSTRUCTION]
【解析】该指令用于指定当前镜像的子镜像进行构建时要执行的指令。
VOLUME
【语法】VOLUME ["dir1", "dir2", ...]
【解析】在容器创建可以挂载的数据卷。
Docker网络模型
为了实现同一个宿主机以及跨宿主机的容器之间网络互联,Docker网络支持5种网络模式
1.none
2.bride
3.host
4.container
5.network-name
查看Docker默认的网络模式有三个
docker network ls
网络模式指定
默认新建的容器使用Bridge模式,创建容器时,docker run命令使用以下选项指定网络模式格式
docker run --network <mode>
docker run --net=<mode>
<mode>: 可以是以下值
bridge
container:<容器名或容器ID>
host
none
docker run --network #再按两下Tab键
bridge container: host ipvlan macvlan none null overlay
bridge网络模式
bridge网络模式概念
1.bridge模式是docker默认的网络模式,即不指定任何模式就是bridge模式,也是使用比较多的模式;
2.此模式创建的容器会为每一个容器分配自己的网络ip等信息,并将容器连接到一个虚拟网桥与外界通信;
3.可以和外部网络之间进行通信,通过SNAT访问外网,使用DNAT可以让容器被外部主机访问,所以此模式也称为NAT模式。
bridge网络模式特点
1.网络资源隔离:不同宿主机的容器无法直接通信,各自使用独立网络;
2.无需手动配置:容器默认自动获取172.17.0.0/16的ip地址,此地址可以修改;
3.可访问外网:利用宿主机的物理网卡,SNAT连接外网;
4.外部主机无法直接访问容器:可以通过配置DNAT接受外网的访问;
5.性能较低:因为需要通过NAT网络转换,所以会带来更多的损耗;
6.端口管理繁琐:每个容器必须手动指定唯一的端口,容易产生端口冲突。
查看bridge模式信息
root@docker:~# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "700fc2656609bcbb19b0565c759eed7368e3d29d1f9b02f78a0701a653312431",
"Created": "2024-05-28T01:33:04.396608546Z",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"c0f5460d0bb5d3ea015707c612f1a903083e0b1da7fd9093d33f282cb4215899": {
"Name": "wordpress",
"EndpointID": "38ed58998c8c76f70c10059967cbc4be891799f36a254b5355c62fd026e27e22",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
Host模式
Host模式概念
1.如果指定host模式启动容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,
2.因此在容器里面查看到的IP信息就是宿主机的信息,
3.访问容器的时候直接使用宿主机IP+容器端口即可,
4.不过容器内除网络以外的其他资源,如:文件系统,系统进程等仍然和宿主机保持隔离。
Host模式特点
1.使用参数-network host指定
2.共享宿主机网络
3.网络性能无损耗
4.网络故障排除相对简单
5.个容器网络无隔离
6.网络字段无法分别统计
7.端口管理困难,容易产生端口冲突
8.不支持端口映射
发布自己的应用
发布一个Java的hello world
@RestController()
public class HelloWorld {
@GetMapping("/hello")
public String hello(){
System.out.println("++++++++++Java: Hello Dockerfile+++++++++++++");
return "Java: hello world Dockerfile";
}
}
编写完成后,打包成jar包(HelloDocker.jar)上传到linux上的某个目录下
编写Dockerfile
FROM openjdk:8u102
LABEL auth="leilei" email="2369005098@qq.com" version="1.0"
COPY HelloDocker.jar HelloJava.jar
ENTRYPOINT ["java","-jar","HelloJava.jar"]
EXPOSE 8080
构建镜像
运行镜像,对外暴露9003端口
[root@localhost java]# docker run --name hello -dp 9003:8080 hello-jave:1.1
6b0d0439511e085faa34ef24515406602b89cc3e7e260570f9c8f4b9d25dbdf4
进入到容器里面查看
查看容器日志
浏览器访问我暴露出的9003端口
ok,java的hello world的小应用程序就以docker容器的方式运行成功了。
Mysql和Redis的Docker安装
Mysql
可以参考docker-hub的官方安装命令docker-hub-mysql
docker run --name mysql -dp 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
MySQL生产安装
为了保证数据的安全性,在生产环境下安装的 mysql 容器,在启动时都会使用数据卷来持久化数据。
docker run --name mysql \
-e MYSQL_ROOT_PASSWORD=root \
-v /root/mysql/data:/var/lib/mysql \
-v /root/mysql/log:/var/log/mysql \
-v /root/mysql/conf:/etc/mysql/conf.d \
-dp 3306:3306 \
mysql:5.7
MySQL集群安装
安装master容器
第一步:启动master容器,指定数据卷路径
docker run --name mysql_master \
-e MYSQL_ROOT_PASSWORD=root \
-v /root/mysql_master/data:/var/lib/mysql \
-v /root/mysql_master/log:/var/log/mysql \
-v /root/mysql_master/conf:/etc/mysql/conf.d \
-dp 3316:3306 \
mysql:5.7
第二步: 新建 my.cnf
[client]
default_character_set=utf8
[mysql]
default_character_set=utf8
[mysqld]
character_set_server=utf8
server_id=01
binlog-ignore-db=mysql
log-bin=master-log-bin
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
slave_skip_errors=1062
第三部:创建用户
mysql> create user 'slave'@'%' identified by '123456';
Query OK, 0 rows affected (0.00 sec)
第四步:给用户赋予权限
mysql> grant replication slave,replication client on *.* to 'slave'@'%';
Query OK, 0 rows affected (0.01 sec)
第五步:查看该用户权限
mysql> show grants for 'slave'@'%';
+-------------------------------------------------------------------+
| Grants for slave@% |
+-------------------------------------------------------------------+
| GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%' |
+-------------------------------------------------------------------+
1 row in set (0.00 sec)
安装slave容器
第一步:启动slave容器,指定数据卷路径
docker run --name mysql_slave \
-e MYSQL_ROOT_PASSWORD=root \
-v /root/mysql_slave/data:/var/lib/mysql \
-v /root/mysql_slave/log:/var/log/mysql \
-v /root/mysql_slave/conf:/etc/mysql/conf.d \
-dp 3326:3306 \
mysql:5.7
第二步:新建my.cnf
[client]
default_character_set=utf8
[mysql]
default_character_set=utf8
[mysqld]
character_set_server=utf8
server_id=02
binlog-ignore-db=mysql
log-bin=slave-log-bin
binlog_cache_size=1M
binlog_format=mixed
expire_logs_days=7
slave_skip_errors=1062
relay_log=relay-log-bin
log_slave_updates=1
read_only=1
第三部:进入容器连接mysql
[root@localhost conf]# docker exec -it mysql_slave /bin/bash
bash-4.2# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.44-log MySQL Community Server (GPL)
Copyright (c) 2000, 2023, Oracle and/or its affiliates.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
配置主从复制
1.查看master状态
mysql> show master status;
+-----------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------------+----------+--------------+------------------+-------------------+
| master-log-bin.000001 | 617 | | mysql | |
+-----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
2.slave 指定 master
在 slave 中通过运行 change master to 命令来指定其要连接的 master 相关信息。
mysql> change master to master_host='10.0.0.226',master_user='slave',master_password='123456',master_port=3316,master_log_file='master-log-bin.000001',master_log_pos=617,master_connect_retry=30,master_retry_count=3;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State:
Master_Host: 10.0.0.226
Master_User: slave
Master_Port: 3316
Connect_Retry: 30
Master_Log_File: master-log-bin.000001
Read_Master_Log_Pos: 617
Relay_Log_File: relay-log-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: master-log-bin.000001
Slave_IO_Running: No
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 617
Relay_Log_Space: 154
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
Master_UUID:
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 3
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
ERROR:
No query specified
3.开启slave
start slave;
此时master和slave已经完成了主从复制,在master上新建一个数据库和数据表已经即时同步到slave上了。
再次验证主从是否读写分离,master可以读写数据,slave只能读数据。
验证slave节点上能否插入数据
查看master上是否有slave插入的数据。master上自然不会有Tony这条数据。
问题所在
slave上可以写数据,因为我们在配置文件中设置的是slave用户的只读权限,而slave节点上我们用的是root用户登录的。此时我们可以设置super用户为只读权限则slave节点就不能插入数据了。
mysql> set global super_read_only=1;
Query OK, 0 rows affected (0.00 sec)
Redis
单机安装Redis
docker run --name myredis \
-v /root/redis/redis.conf:/etc/redis/redis.conf \
-v /root/redis/data:/data \
-dp 6379:6379 \
redis:7.0 \
redis-server /etc/redis/redis.conf
进入redis容器
Redis一主两从集群搭建
现要搭建一个“一主两从”的 Redis 集群。这三个容器的端口号都保持默认,但对外暴露出的端口号分别为 6381、6382、6383。其中,6381 的为 master,另外两个为 slave。
1.复制三份 redis.conf
在两个slave的redis.conf上加上两个如下配置
slave-announce-ip ip地址
slave-announce-port 端口号
2.启动master容器
docker run --name myredis-1 \
-v /root/redis/redis1.conf:/etc/redis/redis.conf \
-v /root/redis/data/6381:/data \
-dp 6381:6379 \
redis:7.0 \
redis-server /etc/redis/redis.conf
启动slave容器
myredis-2
docker run --name myredis-2 \
-v /root/redis/redis2.conf:/etc/redis/redis.conf \
-v /root/redis/data/6382:/data \
-dp 6382:6379 \
redis:7.0 \
redis-server /etc/redis/redis.conf --slaveof 10.0.0.227 6381
myredis-3
docker run --name myredis-3 \
-v /root/redis/redis3.conf:/etc/redis/redis.conf \
-v /root/redis/data/6383:/data \
-dp 6383:6379 \
redis:7.0 \
redis-server /etc/redis/redis.conf --slaveof 10.0.0.227 6381
查看主从关系
master节点上
slave节点上
验证主从是否同步,在master上set一个值之后,两个slave节点可以直接get到
Redis 高可用集群搭建
主从集群存在的问题是,其容灾方式只能采用冷处理方案,无法在生产中使用。所以这里要搭建一个“一主两从三哨兵”的高可用集群,以达到热处理的容灾方案。
对于“一主两从”集群,仍使用前面的即可。下面直接搭建三个 Sentinel 节点的集群。
这三个容器的端口号都保持默认,但对外暴露出的端口号分别为 26381、26382、26383。
1.复制三份 sentinel.conf
复制 sentinel.conf 文件并重命名为 sentinel1.conf。
仅修改两处:
1.指定其要监视的 master 及<quorum>。
2.指定当前 sentinel 对外宣布的 IP 与端口号。其中 IP 为 docker 宿主机的 IP,端口号为其对外暴露的端口号。
2.启动 sentinel
2.1启动mysentinel-1
docker run --name mysentinel-1 \
-v /root/redis/sentinel1.conf:/etc/redis/sentinel.conf \
-dp 26381:26379 \
redis:7.0 \
redis-sentinel /etc/redis/sentinel.conf
2.2启动mysentinel-2
docker run --name mysentinel-2 \
-v /root/redis/sentinel2.conf:/etc/redis/sentinel.conf \
-dp 26382:26379 \
redis:7.0 \
redis-sentinel /etc/redis/sentinel.conf
2.3启动mysentinel-3
docker run --name mysentinel-3 \
-v /root/redis/sentinel3.conf:/etc/redis/sentinel.conf \
-dp 26383:26379 \
redis:7.0 \
redis-sentinel /etc/redis/sentinel.conf
关系查看
以上命令的查看结果说明 sentinel 对 master 的监视成功,说明高可用集群搭建成功。连
接任何一个 sentinel 容器节点查看到的信息与上面的都是相同的。
故障转移测试
为了验证高可用性,现将充当 master 的容器 myredis-1 停掉。
此时,再查看另外两个 redis 容器的状态数据,发现 myredis-2 成为了 myredis-3 的 slave,
myredis-3 成为了新的 master
此时再次启动myredis-1时,发现它成了myredis-3的slave节点
Docker compose
Docker Compose是Docker一个用于定义和管理多容器的容器编排工具
。通过使用Docker Compose,可以在单个YAML文件中配置应用的服务、网络和卷等,简化了多容器应用的部署和管理。解决了手动部署容器的弊端。
安装Docker compose
curl -SL https://github.com/docker/compose/releases/download/v2.26.1/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
赋予docker-compose执行权限
chmod +x /usr/local/bin/docker-compose
手工启动项目的步骤
现有java项目ssrm,windows本地运行结果如下
将项目在windows下使用到的mysql和redis全部转换成linux下的服务,10.0.0.227为我虚拟机的ip,此台机器上安装了mysql3306和redis6379
1.构建镜像
将项目打包成ssrm.jar,编写Dockerfile将其构建成finance:1.0镜像.
2.运行镜像
因为本java项目需要mysql和redis环境,所以我们最先运行了mysql和redis容器,此时我们先后手动启动了三个容器。我对外暴露9000的访问端口。
3.访问项目
项目已经基于容器的方式运行成功了。redis中也是有数据写入的。
访问日志也是正常的
手工启动项目的弊端
手工启动项目不仅繁琐易错,而且还存在一个致命问题:当前应用访问的 mysql 与 redis只能是运行在当前 Docker 宿主机之上的,否则将无法访问到它们。因为在应用的配置文件中已经将 mysql 与 redis 的 IP 进行了硬编码。而使用 Docker Compose 可以解决所有问题
Docker Compose的主要特性
Docker Compose的主要特性
1.简化多容器应用的管理:
使用Compose可以通过单个命令来启动、停止和管理多个容器,而不需要单独管理每个容器。
2.使用YAML文件配置:
Compose使用docker-compose.yml文件来定义应用服务、网络和卷的配置,易于阅读和维护。
3.服务依赖管理:
Compose允许您定义服务之间的依赖关系,确保服务按照正确的顺序启动和停止。
4.环境变量支持:
可以通过.env文件或在docker-compose.yml中使用环境变量,方便配置不同环境的参数。
5.扩展和缩减服务:
Compose支持通过命令轻松扩展或缩减服务的实例数量,以适应负载变化。
docker-compose常用命令
常用命令:
docker-compose up:启动服务。
docker-compose down:停止并删除服务。
docker-compose ps:查看运行中的服务。
docker-compose logs:查看服务日志。
Compose 编排启动项目
1.定义 compose.yml
services:
app:
build: ./
container_name: myapp
ports:
- 9001:8080
volumes:
- ./logs:/var/applogs
depends_on:
- mysql
- redis
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- 3306:3306
volumes:
- /root/mysql/log:/var/log/mysql
- /root/mysql/data:/var/log/mysql
- /root/mysql/conf:/etc/mysql/conf.d
redis:
image: redis:7.0
ports:
- 6379:6379
volumes:
- /root/redis/redis.conf:/etc/redis/redis.conf
- /root/redis/data:/data
command: redis-server /etc/redis/redis.conf
修改application.yml配置文件
将 mysql 与 redis 的主机名修改为它们相应服务的名称。
之后重新打包上传
2.启动所有容器
docker-compose up -d
访问应用
Docker compose已经成功将项目运行起来了。
错误排查,可能会遇到端口占用的情况
3.指定各组件名称
compose2.yml
services:
app:
build: ./
image: finance:3.0
container_name: myapp
ports:
- 9001:8080
volumes:
- ./logs:/var/applogs
networks:
- ab
depends_on:
- leimysql
- leiredis
leimysql:
image: mysql:5.7
container_name: lmysql
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- 3306:3306
volumes:
- /root/mysql/log:/var/log/mysql
- /root/mysql/data:/var/log/mysql
- /root/mysql/conf:/etc/mysql/conf.d
networks:
- ab
leiredis:
image: redis:7.0
container_name: lredis
ports:
- 6379:6379
volumes:
- /root/redis/redis.conf:/etc/redis/redis.conf
- /root/redis/data:/data
networks:
- ab
command: redis-server /etc/redis/redis.conf
networks:
ab:
因为指定了的各个组件的别名redis别名为leiredis,mysql别名为leimysql,所以java程序需要修改相应的服务名后重新打包
docker-compose -f compose2.yml up -d
指定自定义的服务名后,程序访问仍然是正常的
4.查看项目的Docker网络
docker network inspect finance_ab
[root@localhost finance]# docker network inspect finance_ab
[
{
"Name": "finance_ab",
"Id": "468e5c3d0b3bc73ff5060c5db8929a0ee2f5fef8a51051d682d92e073de6eb5e",
"Created": "2024-05-08T11:51:34.792743101+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"29d4052b7322b7a3e3eb06702566ff06376656a0c884fc9ec6b5fc8c7644fb0b": {
"Name": "lmysql",
"EndpointID": "f25454ba1da32168c709c7853d582a5cd6b5b1c9afd6894d375c1ded5c2581ab",
"MacAddress": "02:42:ac:13:00:03",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": ""
},
"4732bdaaa453065cee1eade619381f5baff9e63d8ce75d8abde5cf15c70596d2": {
"Name": "lredis",
"EndpointID": "c4da3f083e4e4f980b8ac96375cd29559c4fe52363ef6d936481a89f0d839332",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
},
"60f6dead3dbca7a7e30eeb72d9b06c20d3f1bc6aaabf73d33d87bd2418f45ba0": {
"Name": "myapp",
"EndpointID": "05459a3e0349be81c79232a770683e27fbaedcf26fae046ed674116e6ea8967e",
"MacAddress": "02:42:ac:13:00:04",
"IPv4Address": "172.19.0.4/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "ab",
"com.docker.compose.project": "finance",
"com.docker.compose.version": "2.26.1"
}
}
]
5.管理服务
docker-compose down 停止服务
docker-compose ps 查看服务状态
docker-compose up --scale leimysql=3 扩展服务实例(例如,增加两个Mysql实例):
Docker管理监控平台
DockerUI
docker run -d -p 7000:9000 -v /var/run/docker.sock:/var/run/docker.sock uifd/ui-for-docker
访问管理页面
Portainer
Portainer可以管理集群,
docker volume create portainer_data
docker run -d -p 8000:8000 -p 9443:9443 -p 7100:9000 \
--name portainer \
--restart=always \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
访问portainer管理页面:ip+端口号(10.0.0.227:7100)
Harbor镜像中心
安装Harbor
wget https://github.com/goharbor/harbor/releases/download/v2.7.1/harbor-offline-installer-v2.7.1.tgz
访问Harbor镜像管理中心,配置文件里默认80端口
Harbor的高可用
Harbor高可用实现方案
1.两台Harbor主机,一台nginx主机,
2.两台Harbor主机相互同步,nginx主机做负载均衡,使用户无感知切换两台Harbor主机。
Harbor安装脚本来自马哥教育王晓春老师
此脚本我在Ubuntu20.04上执行成功了,在RockyLinx8.5中执行失败
#!/bin/bash
#
#********************************************************************
#Author: wangxiaochun
#Date: 2020-02-04
#FileName: install_harbor.sh
#URL: http://www.wangxiaochun.com
#Description: The test script
#Copyright (C): 2020 All rights reserved
#********************************************************************
DOCKER_VERSION="20.10.10"
UBUNTU_DOCKER_VERSION="5:${DOCKER_VERSION}~3-0~`lsb_release -si`-`lsb_release -cs`"
DOCKER_COMPOSE_VERSION=2.6.1
#DOCKER_COMPOSE_VERSION=1.29.2
DOCKER_COMPOSE_FILE=docker-compose-Linux-x86_64
HARBOR_VERSION=2.5.2
HARBOR_BASE=/apps
HARBOR_NAME=harbor.magedu.org
#HARBOR_NAME=`hostname -I|awk '{print $1}'`
HARBOR_IP=`hostname -I|awk '{print $1}'`
HARBOR_ADMIN_PASSWORD=123456
COLOR_SUCCESS="echo -e \\033[1;32m"
COLOR_FAILURE="echo -e \\033[1;31m"
END="\033[m"
. /etc/os-release
color () {
RES_COL=60
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
SETCOLOR_SUCCESS="echo -en \\033[1;32m"
SETCOLOR_FAILURE="echo -en \\033[1;31m"
SETCOLOR_WARNING="echo -en \\033[1;33m"
SETCOLOR_NORMAL="echo -en \E[0m"
echo -n "$1" && $MOVE_TO_COL
echo -n "["
if [ $2 = "success" -o $2 = "0" ] ;then
${SETCOLOR_SUCCESS}
echo -n $" OK "
elif [ $2 = "failure" -o $2 = "1" ] ;then
${SETCOLOR_FAILURE}
echo -n $"FAILED"
else
${SETCOLOR_WARNING}
echo -n $"WARNING"
fi
${SETCOLOR_NORMAL}
echo -n "]"
echo
}
install_docker(){
if [ $ID = "centos" -o $ID = "rocky" ];then
if [ $VERSION_ID = "7" ];then
cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/7/x86_64/stable/
EOF
else
cat > /etc/yum.repos.d/docker.repo <<EOF
[docker]
name=docker
gpgcheck=0
#baseurl=https://mirrors.aliyun.com/docker-ce/linux/centos/8/x86_64/stable/
baseurl=https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/8/x86_64/stable/
EOF
fi
yum clean all
${COLOR_FAILURE} "Docker有以下版本"${END}
yum list docker-ce --showduplicates
${COLOR_FAILURE}"5秒后即将安装: docker-"${DOCKER_VERSION}" 版本....."${END}
${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep 5
yum -y install docker-ce-$DOCKER_VERSION docker-ce-cli-$DOCKER_VERSION \
|| { color "Base,Extras的yum源失败,请检查yum源配置" 1;exit; }
else
dpkg -s docker-ce &> /dev/null && $COLOR"Docker已安装,退出" 1 && exit
apt update || { color "更新包索引失败" 1 ; exit 1; }
apt -y install apt-transport-https ca-certificates curl software-properties-common || \
{ color "安装相关包失败" 1 ; exit 2; }
curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
add-apt-repository "deb [arch=amd64] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
apt update
${COLOR_FAILURE} "Docker有以下版本"${END}
apt-cache madison docker-ce
${COLOR_FAILURE}"5秒后即将安装: docker-"${UBUNTU_DOCKER_VERSION}" 版本....."${END}
${COLOR_FAILURE}"如果想安装其它Docker版本,请按ctrl+c键退出,修改版本再执行"${END}
sleep 5
apt -y install docker-ce=${UBUNTU_DOCKER_VERSION} docker-ce-cli=${UBUNTU_DOCKER_VERSION}
fi
if [ $? -eq 0 ];then
color "安装软件包成功" 0
else
color "安装软件包失败,请检查网络配置" 1
exit
fi
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://si7y70hh.mirror.aliyuncs.com"],
"insecure-registries":["harbor.magedu.org:80"]
}
EOF
systemctl daemon-reload
systemctl enable docker
systemctl restart docker
docker version && color "Docker 安装成功" 0 || color "Docker 安装失败" 1
echo 'alias rmi="docker images -qa|xargs docker rmi -f"' >> ~/.bashrc
echo 'alias rmc="docker ps -qa|xargs docker rm -f"' >> ~/.bashrc
}
install_docker_compose(){
if [ $ID = "centos" -o $ID = "rocky" ];then
${COLOR_SUCCESS}"开始安装 Docker compose....."${END}
sleep 1
if [ ! -e ${DOCKER_COMPOSE_FILE} ];then
#curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/${DOCKER_COMPOSE_FILE} -o /usr/bin/docker-compose
curl -L https://get.daocloud.io/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) -o /usr/bin/docker-compose
else
mv ${DOCKER_COMPOSE_FILE} /usr/bin/docker-compose
fi
chmod +x /usr/bin/docker-compose
else
apt -y install docker-compose
fi
if docker-compose --version ;then
${COLOR_SUCCESS}"Docker Compose 安装完成"${END}
else
${COLOR_FAILURE}"Docker compose 安装失败"${END}
exit
fi
}
install_harbor(){
${COLOR_SUCCESS}"开始安装 Harbor....."${END}
sleep 1
if [ ! -e harbor-offline-installer-v${HARBOR_VERSION}.tgz ] ;then
wget https://github.com/goharbor/harbor/releases/download/v${HARBOR_VERSION}/harbor-offline-installer-v${HARBOR_VERSION}.tgz || ${COLOR_FAILURE} "下载失败!" ${END}
fi
[ -d ${HARBOR_BASE} ] || mkdir ${HARBOR_BASE}
tar xvf harbor-offline-installer-v${HARBOR_VERSION}.tgz -C ${HARBOR_BASE}
cd ${HARBOR_BASE}/harbor
cp harbor.yml.tmpl harbor.yml
sed -ri "/^hostname/s/reg.mydomain.com/${HARBOR_NAME}/" harbor.yml
sed -ri "/^https/s/(https:)/#\1/" harbor.yml
sed -ri "s/(port: 443)/#\1/" harbor.yml
sed -ri "/certificate:/s/(.*)/#\1/" harbor.yml
sed -ri "/private_key:/s/(.*)/#\1/" harbor.yml
sed -ri "s/Harbor12345/${HARBOR_ADMIN_PASSWORD}/" harbor.yml
sed -i 's#^data_volume: /data#data_volume: /data/harbor#' harbor.yml
#mkdir -p /data/harbor
${HARBOR_BASE}/harbor/install.sh && ${COLOR_SUCCESS}"Harbor 安装完成"${END} || ${COLOR_FAILURE}"Harbor 安装失败"${END}
cat > /lib/systemd/system/harbor.service <<EOF
[Unit]
Description=Harbor
After=docker.service systemd-networkd.service systemd-resolved.service
Requires=docker.service
Documentation=http://github.com/vmware/harbor
[Service]
Type=simple
Restart=on-failure
RestartSec=5
ExecStart=/usr/bin/docker-compose -f ${HARBOR_BASE}/harbor/docker-compose.yml up
ExecStop=/usr/bin/docker-compose -f ${HARBOR_BASE}/harbor/docker-compose.yml down
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable harbor &>/dev/null || ${COLOR}"Harbor已配置为开机自动启动"${END}
if [ $? -eq 0 ];then
echo
color "Harbor安装完成!" 0
echo "-------------------------------------------------------------------"
echo -e "请访问链接: \E[32;1mhttp://${HARBOR_IP}/\E[0m"
echo -e "用户和密码: \E[32;1madmin/${HARBOR_ADMIN_PASSWORD}\E[0m"
else
color "Harbor安装失败!" 1
exit
fi
}
docker info &> /dev/null && ${COLOR_FAILURE}"Docker已安装"${END} || install_docker
docker-compose --version &> /dev/null && ${COLOR_FAILURE}"Docker Compose已安装"${END} || install_docker_compose
install_harbor
两台主机之间怎么拷贝文件
root用户可以直接执行普通lei用户下的文件
脚本执行完了,docker,docker-compose,harbor都安装好了