注意!!注意系统内存,一开始我使用阿里云1核1G系统,各种问题,搞了几天,原来是内存不足
一、使用VM虚拟机,安装CentOS7.X系统,并安装和使用Docker
1.1、虚拟机安装CentOS7.X系统
1、登录官网https://www.centos.org/download/下载
本次下载的版本是CentOS-7-x86_64-DVD-1804.iso
2、安装虚拟机
3、安装系统
1.2、安装CentOS7.X,并能连同外网
- 虚拟机中安装CentOS7.X,参考上面步骤或http://blog.51cto.com/13438667/2059926
- 安装完后,启动系统,输入帐号密码登录
- 登录后进入了命令行模式
- 输入命令ping www.baidu.com,看是否能连通
- 出现错误提示name or service not know的解决办法,参考https://blog.csdn.net/phs999/article/details/77448639
- 原因是没有添加DNS或虚拟机网络设备开机时没有启用,
- 一般是没有开启网络设备,DNS可以先不配置,尝试一下开启后不行再设置。
- 添加DNS
- vi /etc/resolv.conf进入设置此文件
- 输入2个命令
- nameserver 8.8.8.8
- nameserver 8.8.4.4
- 然后按ESC,输入:wq,保存退出
- 如果按错了,进入了recording状态,则按ESC后再按q即可退出
- 设置网络设备开机启用
- 输入命令vi /etc/sysconfig/network-scripts/ifcfg,然后按2此TAB键,可以得到网络适配器的提示
- 一般是使用ens33
- 然后输入命令vi /etc/sysconfig/network-scripts/ifcfg-ens33
- 修改里面一个onboot配置为yes
- 然后按ESC,输入:wq,保存退出
- 设置完成后,输入reboot,重启服务器
- 再次输入ping www.baidu.com,应该可以ping通了,ping的时候会一直获取数据,按Ctrl+C即可停止。
1.3、安装Docker,调用它的测试例子
- 查看是否系统自带docker,如果有相关信息则代表有自带docker:docker version
- 删除自带docker:sudo yum -y remove docker
- 安装yum-utils,使用其yum-config-manager设置Yum源:sudo yum install -y yum-utils
- 设置Yum源:sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 更新Yum缓存:sudo yum makecache fast
- 安装Docker CE:sudo yum -y install docker-ce
- 启动Docker后台服务:sudo systemctl start docker
- 查看docker版本:docker --version
- 启动测试例子:docker run hello-world
由于本次没有这个镜像,所以会从往网上下载
1.4、使用阿里云镜像加速器
可以提升获取Docker官方镜像的速度
注册阿里云,进入控制台,点击左上角按钮,展开产品列表,搜索“镜像”,进入容器镜像服务
复制下方命令,即可完成配置
然后可以使用vi /etc/docker/daemon.json命令,确认是否保存了配置
1.5、Docker常用命令展示
Docker镜像常用命令:
- 搜索镜像:搜索存放在Docker Hub中的镜像:docker search java
- 下载镜像从Docker Registry上下载镜像到本地
- 下载最新版本Java镜像:docker pull java
- 从指定的Docker Registry中下载标签为7的Java镜像:docker pull reg.itmuch.com/java:7
列出已下载镜像:docker images
删除本地镜像
-
- 删除指定镜像:docker rmi hello-world
- 删除所有镜像,-f表示强制删除:docker rmi -f $(docker images)
Docker容器常用命令:
- 新建并启动容器
- docker run
- -d选项:后台运行
- -P选项:随机端口映射
- -p选项:指定端口映射,4种格式
- ip:hostPort:containerPort
- ip::containerPort
- hostPort:containerPort
- containerPort
- --network选项:指定网络模式
- --network=bridge:默认选项,表示连接到默认的网桥
- --network=host:容器使用宿主机的网络
- --network=container:Name_or_ID:告诉Docker让新建的容器使用已有容器的网络配置。
- --network=none:不配置该容器的网络,用户可以自定义网络配置。
- 例子:docker run java /bin/echo 'Hello World'
- 终端会打印Hello World字样,等同本地直接执行/bin/echo 'Hello World'
- 例子:docker run -d -p 91:80 nginx
- 启动一个Nginx容器,-d表示后台运行,-p 91:80 表示开放容器端口80到宿主机端口91
- 然后可以访问http://Docker宿主机IP:91/,看到nginx首页
- 列出容器:docker ps
- 停止容器:docker stop 容器ID/容器名称
- 强制停止容器:docker kill 容器ID/容器名称
- 启动已停止的容器:docker start 容器ID/容器名称
- 重启容器:docker restart 容器ID/容器名称
- 进入容器
- docker attach 容器ID/容器名称
- 这种方式不方便,多个窗口同时attach到同一个容器时,所有窗口同步显示。如果一个窗口发生阻塞,其它窗口也无法操作。
- 使用nsenter进入容器
- 先找到容器第一个进程的ID
- docker inspect --format "{{.State.Pid}}" 容器ID
- 会输出一个进程ID
- 进入容器
- nsenter --target 进程ID --mount --uts --ipc --net --pid
- 删除容器:docker rm 容器ID/容器名称
- 删除所有容器:docker rm -f $(docker ps -a -q)
二、把Spring Boot项目的jar文件放到Docker部署
2.1、创建镜像生成脚本DockerFile
创建一个名为Dockerfile的文件,输入以下代码
FROM java:8 VOLUME /tmp ADD lt-eureka-1.1.6.jar app.jar RUN bash -c 'touch /app.jar' RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone EXPOSE 1000 ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
2.2、Spring Boot项目生成Jar文件
使用Maven命令:mvn clean package即可打包
注意一个问题:spring boot项目打包的jar包运行时提示:no main manifest attribute
此时可以在本次测试一下java -jar xx.jar直接运行你的jar包是否报错
这个报错的原因是:maven打包时没有把主清单属性打包进去,参考https://blog.csdn.net/u010429286/article/details/79085212
在pom文件中加入插件即可:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
2.3、使用XFTP把文件上传到服务器
我们需要上传jar文件和DockerFile到CentOS服务器
使用XFTP工具,百度XFTP到官网即可下载,个人使用免费
在CentOS上输入命令ifconfig,查看系统的IP地址
创建文件夹
- mkdir ltmicro
- mkdir ltmicro/eureka
然后可以查看是否成功
- ls
- ls ltmicro
- ls -l
- ls ltmicro -l
在Windows系统上,打开XFTP工具
需要上传的文件只要拖动即可,还能新建文件夹等
2.4、使用Docker部署jar程序
前面我们通过XFTP创建ltmicro/eureka目录,并上传Dockerfile和生成jar包
然后运行命令创建Docker镜像:docker build -t eureka ltmicro/eureka
成功后,查看系统已生成的镜像:docker images
使用镜像生成并运行一个容器:docker run --name eureka_1 -d -p 1000:1000 eureka
查看容器运行的控制条输出日志:docker logs -f eureka_1
2.5、测试程序
访问虚拟机ip:1000,即可访问到部署在Docker中的项目了
三、使用Docker-compose编排微服务
如果我们有多个程序需要集中运行,如微服务系统,如果都用dockerfile进行部署,会十分麻烦。
可以使用Docker-compose来对这些容器进行编排,按照规定的方式进行启动,免除复杂的操作。
3.1、安装docker-compose
- 访问docker-compose的github主页的版本页面:https://github.com/docker/compose/releases
- 会有最新版本的安装语句
例如
curl -L https://github.com/docker/compose/releases/download/1.22.0-rc1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
- 复制命令到CentOS系统中进行安装
- 然后执行命令更改compose工具的执行权限:chmod +x /usr/local/bin/docker-compose
- 查看安装版本:docker-compose version
- 查看帮助:docker-compose -h
- 查看某个命令的帮助:docker-compose help down
- 如果github的方式下载慢,也可以尝试sudo pip install docker-compose这种安装方式
3.2、编写编排脚本
- 创建一个docker-compose.yml文件
- 输入以下脚本
eureka:
build: ./eureka
ports:
- "1000:1000"
- 使用XFTP上传到ltmicro目录下
- 然后输入命令来到docker-compose.yml文件所在目录:
- cd ltmicro
- 执行命令:
- docker-compose up -d
- 这个命令会自动执行下载镜像、创建镜像、创建容器、运行容器、运行程序的工作,一句命令则完成了我们上面的所有代码的工作。
- 停止脚本相关容器
- docker-compose down --rmi all
- 这个命令会自动执行停止程序、停止容器、删除容器、删除镜像的工作。
四、Docker部署Redis、MySQL
4.1、Docker部署Redis
- 获取Redis镜像:docker pull redis:3.2
- 创建Docker容器并运行Redis
-
docker run --name redis -p 6379:6379 -v $PWD/data:/data -d redis:3.2 redis-server --appendonly yes
- -p 6379:6379 : 将容器的6379端口映射到主机的6379端口
- -v $PWD/data:/data : 将主机中当前目录下的data挂载到容器的/data
- redis-server --appendonly yes : 在容器执行redis-server启动命令,并打开redis持久化配置
-
docker run --name redis -p 6379:6379 -v $PWD/data:/data -d redis:3.2 redis-server --appendonly yes
- 查看运行情况:docker ps
- 尝试连接装载redis的容器
- docker exec -it 43f7a65ec7f8 redis-cli
- 然后输入info,可以看到相关信息,代表成功连接
4.2、Docker部署MySQL
4.2.1、使用Docker命令创建
- 查找Docker Hub上的mysql镜像:docker search mysql
- 拉取官方的镜像,标签为5.6:docker pull mysql:5.6
- 运行MySQl容器(容器内mysql默认3306端口,所以内部端口要用3306,4401为服务器暴露端口。如果要修改容器内MySQL端口则需要修改配置文件;指定容器数据、日志、配置文件地址,会自动创建对应文件夹)
- docker run -p 4401:3306 --name mysql4401 -v $PWD/conf:/etc/mysql/conf.d -v $PWD/logs:/logs -v $PWD/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
- 进入容器:docker exec -it mysql4401 bash
- 登录MySQL:mysql -uroot -p123456
- 查看用户信息:select host,user,plugin,authentication_string from mysql.user;
- 修改用户权限,支持外网访问:grant all privileges on *.* to root@"%" identified by "你的密码" with grant option;
- 更新用户权限:FLUSH PRIVILEGES;
- 退出容器:CTRL+P+Q
五、多个微服务部署时需要解决的问题
5.1、同docker-compose.yml文件下的容器之间通讯
使用同一个docker-compose.yml文件部署多个容器时,docker默认为这些容器创建同一个网络。
在同一个网络下,容器之间可以直接通过容器名称来直接访问。
所以,通过以下方式即可实现容器之间通讯:
1、修改程序的配置文件,支持环境变量取值
eureka: client: # 注册到注册中心的地址 service-url: defaultZone: http://me:1234@${EUREKA_HOST:localhost}:${EUREKA_PORT:1000}/eureka # 客户端定时获取服务器注册表的间隔时间,默认30 registry-fetch-interval-seconds: 10
2、修改docker-compose.yml文件,使用容器名作为环境变量传入
version: '2' services: eureka: build: ./eureka ports: - "1000:1000" auth: build: ./auth ports: - "2000:2000" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000
5.2、不同docker-compose.yml文件下的容器之间通讯
原理同上,可以将这些容器放置到同一个网络下即可。
参考:https://www.cnblogs.com/jsonhc/p/7823286.html
network配置参考:https://blog.csdn.net/Kiloveyousmile/article/details/79830810
在实际应用过程,我们可以考虑以下方案:
- 手动创建网络:docker network create my_net
- 查看当前network列表:docker network ls
- 单独运行的容器,可以通过network参数设置对应网络:docker run --name redis --network my_net -p 6379:6379 -v $PWD/data:/data -d redis:3.2 redis-server --appendonly yes
- 使用docker-compose.yml运行的容器,设置network有2种方式:
- 修改默认值
version: '2' services: eureka: build: ./eureka ports: - "1000:1000" auth: build: ./auth ports: - "2000:2000" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 networks: default: external: name: my_net
-
- 为每个服务单独配置
version: '2' services: eureka: build: ./eureka ports: - "1000:1000" networks: - "ex_my_net" auth: build: ./auth ports: - "2000:2000" networks: - "ex_my_net" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 networks: ex_my_net: external: name: my_net
5.3、调用顺序问题
在开发过程中,我们一般是先运行注册中心,运行完成后,再运行认证中心;认证中心运行完成,在运行网关,然后再到通用权限系统。
即使docker-compose中使用了depends_on,只会控制其开始启动的先后顺序,而不会等到某个启动完成才启动下一个。
方案:使用wait-for-it镜像(还有其他工具自行研究)
原理:使用wait-for-it包裹该容器后,容器启动后,会检测其需要等待的服务所在端口是否已开放;端口开放代表该服务已启动完毕,才会运行这个被包裹容器。
用法:
1、到github:https://github.com/vishnubob/wait-for-it下载wait-for-it.sh,然后通过XFTP上传到服务器中
2、需要等待其他容器才启动的容器,对应的dockerfile加上语句
ADD wait-for-it.sh /wait-for-it.sh
代表需要把这个文件复制到容器中
3、 docker-compose文件中,加入相应命令
zuul: build: ./zuul ports: - "3000:3000" depends_on: - eureka - auth links: - redis volumes: - ./wait-for-it.sh:/wait-for-it.sh entrypoint: /wait-for-it.sh auth:2000 -t 600 -- command: java -Djava.security.egd=file:/dev/./urandom -jar /app.jar environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 - AUTH_HOST=auth - AUTH_PORT=2000
5.4、内存管理问题
六、微服务系统部署到阿里云CentOS上去
6.1、项目介绍
- 项目一共有5个微服务,分别是:Eureka注册中心,OAuth认证服务器,Zuul网关,Upms通用权限系统,Inventory进销存系统
- 运行顺序要求:Zuul网关需要在Oauth认证服务器启动完成后才能启动,否则会报错关闭掉;其它服务可以一起启动,没有要求
6.2、操作流程
- 阿里云使用公用镜像安装CentOS系统
- 这里使用CentOS7.3版本,之前用过CentOS7.4版本,出现一些问题,但是不肯定这些问题是由于版本产生,还是由于当时操作原因产生的。
- 使用的是ID为m-wz90dpguuze302fl71ad的【Java运行环境(Centos7 64 | JDK8|Tomcat8)】镜像
- 使用阿里云公共镜像中的CentOS7.3
- 测试ping www.baidu.com看是否连通外网,如果不连通,按照1.2的做法处理
- 安装docker
- 查看是否安装docker:docker version
- 删除自带docker:sudo yum -y remove docker
- 安装yum-utils:sudo yum install -y yum-utils
- 设置Yum源:sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
- 更新Yum缓存:sudo yum makecache fast
- 安装Docker CE:
sudo yum -y install docker-ce
-
启动Docker后台服务:
sudo systemctl start docker
-
查看docker版本:docker --version
- 设置docker镜像加速器:登录阿里云,参考https://cr.console.aliyun.com/cn-shenzhen/mirrors
- 使用docker创建一个网络,使容器之间能相互通信:docker network create my_net
- 使用docker在上面的网络中,运行一个redis容器,并命名容器为redis
- 获取Redis镜像:docker pull redis:3.2
- 运行Redis容器:docker run --name redis --network my_net -p 6379:6379 -v $PWD/redis/data:/data -d redis:3.2 redis-server --appendonly yes
- 尝试连接装载redis的容器
- docker exec -it 43f7a65ec7f8 redis-cli
- 然后输入info,可以看到相关信息,代表成功连接
- 使用docker在上面的网络中,运行一个MySQL容器,并名为容器为mysql
- 拉取官方的镜像,标签为5.6:docker pull mysql:5.6
- 运行MySQl容器,指定容器数据、日志、配置文件地址,会自动创建对应文件夹:
- docker run -p 3306:3306 --name mysql --network my_net -v $PWD/mysql/conf:/etc/mysql/conf.d -v $PWD/mysql/logs:/logs -v $PWD/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.6
- 进入容器:docker exec -it mysql bash
- 登录MySQL:mysql -uroot -p123456
- 查看用户信息:select host,user,plugin,authentication_string from mysql.user;
- 修改用户权限,支持外网访问:grant all privileges on *.* to root@"%" identified by "你的密码" with grant option;
- 更新用户权限:FLUSH PRIVILEGES;
- 退出容器:CTRL+P+Q
- 打包5个微服务的jar包
- 参考2.2,为程序加入打包插件
- 参考5.1,对程序的配置进行修改,支持环境变量传入
- 然后使用Idea中的Maven Package命令生成对应jar包
- 使用FTP上传的所需文件
- Dockerfile的形式参考2.1
- docker-compose文件如下
version: '2' services: eureka: build: ./eureka ports: - "1000:1000" auth: build: ./auth ports: - "2000:2000" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 - MYSQL_HOST=mysql - MYSQL_PORT=3306 - MYSQL_USER=root - MYSQL_PASSWORD=123456 zuul: build: ./zuul ports: - "3000:3000" volumes: - ./wait-for-it.sh:/wait-for-it.sh entrypoint: /wait-for-it.sh auth:2000 -t 600 -- command: java -Djava.security.egd=file:/dev/./urandom -jar /app.jar environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 - AUTH_HOST=auth - AUTH_PORT=2000 upms: build: ./upms ports: - "4000:4000" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 - MYSQL_HOST=mysql - MYSQL_PORT=3306 - MYSQL_USER=root - MYSQL_PASSWORD=123456 inv: build: ./inventory ports: - "5000:5000" environment: - REDIS_HOST=redis - REDIS_PORT=6379 - EUREKA_HOST=eureka - EUREKA_PORT=1000 - MYSQL_HOST=mysql - MYSQL_PORT=3306 - MYSQL_USER=root - MYSQL_PASSWORD=123456 networks: default: external: name: my_net
-
- 使用FTP把ltmicro文件夹上传到root目录下
- 并为wait-for-it.sh文件设置所有权限
- 安装docker-compose
curl -L https://github.com/docker/compose/releases/download/1.22.0-rc1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
-
- 然后执行命令更改compose工具的执行权限:chmod +x /usr/local/bin/docker-compose
- 查看安装版本:docker-compose version
- 查看帮助:docker-compose -h
- 查看某个命令的帮助:docker-compose help down
- 运行docker-compose编排文件
- 转到目录:cd ltmicro
- 执行命令:docker-compose up -d
- 停止和删除相关容器:docker-compose down --rmi all
问题:
以下问题可能是我购买的云服务器内存不足引发的,这个需要留意下。
1、docker无法启动
提示:Job for docker.service failed because the control process exited with error
解决方法:
以下为一个找到的方案,但是实际中,是不知道是因为我在阿里云使用了CentOS7.4系统的问题还是其中安装软件的问题,后来更换阿里云官方镜像CentOS7.3后则解决问题了。
参考:https://blog.csdn.net/qq_35904833/article/details/74189383
# rm -rf /var/lib/docker/ # vim /etc/docker/daemon.json 添加以下内容 { "graph": "/mnt/docker-data", "storage-driver": "overlay" } 重启服务 systemctl restart docker-data
2、各种问题找到的一个可能原因
如上面的,以及No such file or directory,需要升级内核?yum update即可?https://blog.csdn.net/github_39599694/article/details/79563573
3、No such file or directory
使用wait-for-it.sh的时候,提示No such file or directory,是以为该文件被打开过,保存后,编码改变了。
可以参考:https://blog.csdn.net/huoyunshen88/article/details/41575225
4、Docker内服务通过外网访问本机的MySQL
在QQ群看到的一个问题,在这里记录一下,他说执行grant all privileges on *.* to root@'%' identified by '******'就可以了
——基础知识:
1、Dockerfile详解
Dockerfile用于定制镜像,把镜像的每一层修改、安装、构建、操作的命令都写入一个脚本,进行集中管理。
注意,Dockerfile中每一个指令都会增加一层镜像,
1.1、FROM指令
用于选择基础镜像
- 在 Docker Store 上有非常多的高质量的官方镜像
- 可以直接拿来使用的服务类的镜像:nginx 、 redis 、 mongo 、mysql 等;
- 方便开发、构建、运行各种语言应用的镜像:node 、 openjdk 、 python 等;
- 更为基础的操作系统镜像:ubuntu 、 debian 、 centos 等;
- 空白镜像:scratch 。这个镜像是虚拟的概念,并不实际存在,它表示一个空白的镜像。
1.2、RUN指令
用于执行命令行命令
- 2种格式:
- shell 格式: RUN <命令> ,就像直接在命令行中输入的命令一样
- exec 格式: RUN ["可执行文件", "参数1", "参数2"]
- Dockerfile中可以写多个RUN命令,但是每一个命令会增加一层镜像,所以不应该这么做
- 正确写法,应该使用\换行和&&连接:
- FROM debian:jessie
- RUN buildDeps='gcc libc6-dev make' \
- && apt-get update \
- && apt-get install -y $buildDeps \
FROM debian:jessie RUN buildDeps='gcc libc6-dev make'\&& apt-get update \&& apt-get install -y$buildDeps\