在23号刚刚学完新版本的docker还想说回去继续学习老版本的springcloud课程里面的docker 结果一看黑马首页新版本课程出了,绷不住了。以下是我学习新版本docker的笔记,记录了我学习过程遇到的各种bug和解决,也参考了黑马老师的笔记:Docsz
一、Docker镜像官网网站
地址:https://hub.docker.com/
貌似我进入这个网站需要“魔法”,应该可能只是我吧。/狗头
二、防火墙开启端口
先提前去防火墙开启好端口,项目中80,8080,3306都是需要开启的,80是nginx的端口,3306是mysql,8080是项目需要的端口。
1、查看防火墙是否开启
systemctl status firewalld
2、开启、关闭、重启防火墙
systemctl start firewalld
systemctl stop firewalld
firewall-cmd --reload
3、查看所有开启的端口
firewall-cmd --list-ports
这些端口我已经提前开启了。
4、防火墙开启端口访问
命令含义: --zone #作用域 --add-port=80/tcp #添加端口,格式为:端口/通讯协议 --permanent #永久生效,没有此参数重启后失效
firewall-cmd --zone=public --add-port=80/tcp --permanent
注意:开启后重启防火墙才能生效!!!
firewall-cmd --reload
重启后可以再次查看开放的端口检验一下
firewall-cmd --list-ports
以此开启3306和8080端口
firewall-cmd --zone=public --add-port=8080/tcp --permanent
firewall-cmd --zone=public --add-port=3306/tcp --permanent
参考博文:linux:centos7开启80端口,开放外网访问_开放80端口-CSDN博客
三、Docker基础
1、常见命令
命令 | 说明 | 文档地址 |
---|---|---|
docker pull | 拉取镜像 | docker pull |
docker push | 推送镜像到DockerRegistry | docker push |
docker images | 查看本地镜像 | docker images |
docker rmi | 删除本地镜像 | docker rmi |
docker run | 创建并运行容器(不能重复创建) | docker run |
docker stop | 停止指定容器 | docker stop |
docker start | 启动指定容器 | docker start |
docker restart | 重新启动容器 | docker restart |
docker rm | 删除指定容器 | docs.docker.com |
docker ps | 查看容器 | docker ps |
docker logs | 查看容器运行日志 | docker logs |
docker exec | 进入容器 | docker exec |
docker save | 保存镜像到本地压缩文件 | docker save |
docker load | 加载本地压缩文件到镜像 | docker load |
docker inspect | 查看容器详细信息 | docker inspect |
其中,我一般用最多的是以下命令: 因为每次登录虚拟机就都需要启动一下容器,来源于我没有设置容器开机自启动。。。
docker images | 查看本地镜像 | docker images |
docker rmi | 删除本地镜像 | docker rmi |
docker stop | 停止指定容器 | docker stop |
docker start | 启动指定容器 | docker start |
docker restart | 重新启动容器 | docker restart |
docker rm | 删除指定容器 | docs.docker.com |
docker ps | 查看容器 | docker ps |
docker logs | 查看容器运行日志 | docker logs |
docker exec | 进入容器 | docker exec |
docker inspect | 查看容器详细信息 | docker inspect |
默认情况下,每次重启虚拟机我们都需要手动启动Docker和Docker中的容器。通过命令可以实现开机自启:
# Docker开机自启
systemctl enable docker# Docker容器开机自启
docker update --restart=always [容器名/容器id]
下面这些是我目前创建的容器:
# 查看运行中容器
docker ps
# 也可以加格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
这里的dps是下面起别名后才有的指令。
2、命令起别名
为什么:给常用Docker命令起别名,方便我们访问
# 1、通过命令页面去修改/root/.bashrc文件
vi /root/.bashrc# 2、进入/root,去修改.bashrc文件
(1)修改/root/.bashrc文件
通过命令页面去修改,个人决定比较麻烦,下面是步骤:
这里我切换插入模式是点击右边键盘的Ins,我个人的电脑是数字的0,我禁用了数字键,所以点击0是开启插入模式。
输入完成后,执行接下来步骤。
正常保存并退出:按
Esc
,然后输入:wq
,再按Enter。
不保存直接退出:按
Esc
,然后输入:q!
,再按Enter
。
(2)进入/root,去修改.bashrc文件
这个是直接用finalshell里面的编辑工具,这里我使用外部的NotePad++。
一般来说先设置外部编辑器,这里我设置了nodepad++,因为比较方便。
然后双击那个文件,正常修改,然后ctrl+s保存即可
设置号命令别名后极大方便使用命令。
3、部署容器及镜像
(1)MySQL
docker run -d \--name mysql \-p 3306:3306 \-e TZ=Asia/Shanghai \-e MYSQL_ROOT_PASSWORD=123 \mysql
这边建议直接在窗口里面输入不是用输入框。下面是黑马老师的结果,大差不差。
上面这个方式是创建容器及其镜像,及其方便。下面是解读:
docker run -d :创建并运行一个容器,-d则是让容器以后台进程运行
--name mysql : 给容器起个名字叫mysql,你可以叫别的
-p 3306:3306 : 设置端口映射容器是隔离环境,外界不可访问。但是可以将宿主机端口映射容器内到端口,当访问宿主机指定端口 时,就是在访问容器内的端口了。容器内端口往往是由容器内的进程决定,例如MySQL进程默认端口是3306,因此容器内端口一定是3306;而宿主机端口则可以任意指定,一般与容器内保持一致。格式: -p 宿主机端口:容器内端口,示例中就是将宿主机的3306映射到容器内的3306端口
-e TZ=Asia/Shanghai : 配置容器内进程运行时的一些参数格式:-e KEY=VALUE,KEY和VALUE都由容器内进程决定案例中,TZ=Asia/Shanghai是设置时区;MYSQL_ROOT_PASSWORD=123是设置MySQL默认密码
mysql : 设置镜像名称,Docker会根据这个名字搜索并下载镜像格式:REPOSITORY:TAG,例如mysql:8.0,其中REPOSITORY可以理解为镜像名,TAG是版本号在未指定TAG的情况下,默认是最新版本,也就是mysql:latest
镜像的名称不是随意的,而是要到DockerRegistry中寻找,镜像运行时的配置也不是随意的,要参考镜像的帮助文档,这些在DockerHub网站或者软件的官方网站中都能找到。
(2)Nginx
分步来部署容器和镜像
- 拉取镜像:
# 拉取Nginx镜像
docker pull nginx
执行后查看镜像:
# 查看镜像
docker images
- 创建并允许Nginx容器
# 创建并允许Nginx容器
docker run -d --name nginx -p 80:80 nginx
下面可以几个指令测试:
# 停止容器
docker stop nginx# 启动nginx容器
docker start nginx# 格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"# 查看容器详细信息
docker inspect nginx
4、数据卷
目的:容器提供程序的运行环境,但是程序运行产生的数据、程序运行依赖的配置都应该与容器解耦。
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
如上,将Nginx容器里面的conf和html文件映射到宿主机里面。
步骤:创建两个数据卷:conf
、html,
Nginx容器内部的conf
目录和html
目录分别与两个数据卷关联。而数据卷conf和html分别指向了宿主机的/var/lib/docker/volumes/conf/_data
目录和/var/lib/docker/volumes/html/_data
目录。
提示:
/var/lib/docker/volumes
这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data
。
(1)数据卷命令
命令 | 说明 | 文档地址 |
---|---|---|
docker volume create | 创建数据卷 | docker volume create |
docker volume ls | 查看所有数据卷 | docs.docker.com |
docker volume rm | 删除指定数据卷 | docs.docker.com |
docker volume inspect | 查看某个数据卷的详情 | docs.docker.com |
docker volume prune | 清除数据卷 | docker volume prune |
(2)数据卷挂载
注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。所以接下来nginx和mysql容器都先删除后再挂载!!!
- Nginx数据卷挂载
参考官方文档:https://hub.docker.com/_/nginx
# 1.首先创建容器并指定数据卷,注意通过 -v 参数来指定数据卷
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx# 2.然后查看数据卷
docker volume ls# 3.查看数据卷详情
docker volume inspect html
- MySQL 数据卷挂载
采用挂载本地目录或文件的方式--缘由:数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便
注意:本地目录或文件必须以 /
或 ./
开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名。
# 挂载本地目录
-v 本地目录:容器内目录
# 挂载本地文件
-v 本地文件:容器内文件-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
先提前在虚拟机里面root目录下准备好mysql文件,里面有conf和init,在里面放自己的配置初始化SQL脚本和配置文件
其中,hm.cnf主要是配置了MySQL的默认编码,改为utf8mb4;而hmall.sql则是后面我们要用到的黑马商城项目的初始化SQL脚本。(这里是黑马老师的资料)
实现本地目录挂载:
# 1.删除原来的MySQL容器
docker rm -f mysql# 2.进入root目录
cd ~# 3.创建并运行新mysql容器,挂载本地目录
docker run -d \--name mysql \-p 3306:3306 \-e TZ=Asia/Shanghai \-e MYSQL_ROOT_PASSWORD=123 \-v ./mysql/data:/var/lib/mysql \-v ./mysql/conf:/etc/mysql/conf.d \-v ./mysql/init:/docker-entrypoint-initdb.d \mysql
可以通过下面命令测试:
# 1.查看root目录,可以发现~/mysql/data目录已经自动创建好了
ls -l mysql# 2.查看data目录,会发现里面有大量数据库数据,说明数据库完成了初始化
ls -l data
5、镜像
镜像中包含了程序运行需要的系统函数库、环境、配置、依赖,能让我们快速跨操作系统部署应用而忽略其运行环境、配置。
打包镜像也是分成这么几步:
- 准备Linux运行环境(java项目并不需要完整的操作系统,仅仅是基础运行环境即可)
- 安装并配置JDK
- 拷贝jar包
- 配置启动脚本
(1)Dockerfile
Docker就提供了自动打包镜像的功能,提供的一种记录镜像结构的文件就称为Dockerfile。
官方文档:Dockerfile reference | Docker Docs
语法比较多,比较常用的有:
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 |
|
ENV | 设置环境变量,可在后面指令使用 |
|
COPY | 拷贝本地文件到镜像的指定目录 |
|
RUN | 执行Linux的shell命令,一般是安装过程的命令 |
|
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
有人提供了基础的系统加JDK环境,在此基础上制作java镜像,就可以省去JDK的配置了。
# 基础镜像
FROM openjdk:11.0-jre-buster
# 设定时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
这个文件一般在写项目的时候准备。
(2)构建镜像
将课前资料提供的docker-demo.jar
包以及Dockerfile
拷贝到虚拟机的/root/demo
目录:
执行命令,构建镜像:
# 进入镜像目录
cd /root/demo# 开始构建
# 1、在当前目录下指定
docker build -t docker-demo:1.0 .# 2、直接指定Dockerfile目录
docker build -t docker-demo:1.0 /root/demo
介绍:
-t docker-demo:1.0 :-t参数是指定镜像的名称(repository和tag)
. : 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以指定的是.代表当前目录,也可以直接指定Dockerfile目录:
测试:(下面都用黑马的笔记)
# 查看镜像列表:
docker images
# 结果
REPOSITORY TAG IMAGE ID CREATED SIZE
docker-demo 1.0 d6ab0b9e64b9 27 minutes ago 327MB
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB# 尝试运行该镜像# 1.创建并运行容器
docker run -d --name dd -p 8080:8080 docker-demo:1.0
# 2.查看容器
dps
# 结果
CONTAINER ID IMAGE PORTS STATUS NAMES
78a000447b49 docker-demo:1.0 0.0.0.0:8080->8080/tcp, :::8090->8090/tcp Up 2 seconds dd
f63cfead8502 mysql 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp Up 2 hours mysql# 3.访问
curl localhost:8080/hello/count
# 结果:
<h5>欢迎访问黑马商城, 这是您第1次访问<h5>
6、网络
容器的网络IP其实是一个虚拟的IP,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能MySQL容器的IP会发生变化,连接会失败。可借助于docker的网络功能来解决这个问题。官方文档:docker network | Docker Docs
命令 | 说明 | 文档地址 |
---|---|---|
docker network create | 创建一个网络 | docker network create |
docker network ls | 查看所有网络 | docs.docker.com |
docker network rm | 删除指定网络 | docs.docker.com |
docker network prune | 清除未使用的网络 | docs.docker.com |
docker network connect | 使指定容器连接加入某网络 | docs.docker.com |
docker network disconnect | 使指定容器连接离开某网络 | docker network disconnect |
docker network inspect | 查看网络详细信息 | docker network inspect |
说简单一点就是:一个ip地址里面容器可能位置会变,但是容器的名字是不会变的,所以可以构建一个干净的网络,网络是联桥模式才能实现同一个网络ip内容器互相访问。
(1)创建网络
# 1.首先通过命令创建一个网络
docker network create hmall# 2.然后查看网络
docker network ls# 除了hmall和heima以外,其它都是默认的网络
(2)容器加入网络
# 让dd,mysql,nginx都加入该网络,注意,在加入网络时可以通过--alias给容器起别名
# 这样该网络内的其它容器可以用别名互相访问!
# 1.mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias db
# 2.nginx容器,指定别名为ng,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias ng
# 3.dd容器,也就是我们的java项目
docker network connect hmall dd
查看网络里面指定容器
# docker network inspect [OPTIONS] NETWORK [NETWORK...]
docker network inspect nginx NETWORK hmall
四、项目部署
1、部署Java项目
(1)修改yml配置,保证信息一致
(2)项目打包
下面是之前我自己写的一个项目,打包步骤差不多:
(3)部署
在黑马的项目中打包后还有一个配置文件Dockerfile,到时候讲打包好的jar包和配置文件一起上传到
虚拟机的root
目录,当然这个目录也是自定义的。
(4)构建镜像
# 1.构建项目镜像,不指定tag,则默认为latest
docker build -t hmall .# 2.查看镜像
docker images
# 结果
REPOSITORY TAG IMAGE ID CREATED SIZE
hmall latest 0bb07b2c34b9 43 seconds ago 362MB
docker-demo 1.0 49743484da68 24 hours ago 327MB
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB# 3.创建并运行容器,并通过--network将其加入hmall网络,这样才能通过容器名访问mysql
docker run -d --name hmall --network hmall -p 8080:8080 hmall
测试:通过浏览器访问:http://你的虚拟机地址:8080/search/list
2、部署前端
(1)将nginx放在指定目录下
hmall-portal
和hmall-admin
是前端代码,需要基于nginx部署。
其中:
- html是静态资源目录,我们需要把hmall-portal以及hmall-admin都复制进去
- nginx.conf是nginx的配置文件,主要是完成对html下的两个静态资源目录做代理
把整个nginx目录上传到虚拟机的/root
目录下:
(2)Nginx数据卷挂载
通过指定目录挂载的方式,之前我们已经把nginx放在指定目录下,接下来挂载就行。
然后创建nginx容器并完成两个挂载:
- 把/root/nginx/nginx.conf挂载到/etc/nginx/nginx.conf
- 把/root/nginx/html挂载到/usr/share/nginx/html由于需要让nginx同时代理hmall-portal和hmall-admin两套前端资源,因此我们需要暴露两个端口:
- 18080:对应hmall-portal
- 18081:对应hmall-admin
docker run -d \--name nginx \-p 18080:18080 \-p 18081:18081 \-v /root/nginx/html:/usr/share/nginx/html \-v /root/nginx/nginx.conf:/etc/nginx/nginx.conf \--network hmall \nginx
测试,通过浏览器访问:http://你的虚拟机ip:18080
3、DockerCompose
Docker Compose可以帮助我们实现多个相互关联的Docker容器的快速部署。它允许用户通过一个单独的 docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。官方文档:Compose file version 3 reference | Docker Docs
docker run 参数 | docker compose 指令 | 说明 |
---|---|---|
--name | container_name | 容器名称 |
-p | ports | 端口映射 |
-e | environment | 环境变量 |
-v | volumes | 数据卷配置 |
--network | networks | 网络 |
(1)编写docker-compose
文件
version: "3.8"services:mysql:image: mysqlcontainer_name: mysqlports:- "3306:3306"environment:TZ: Asia/ShanghaiMYSQL_ROOT_PASSWORD: 123volumes:- "./mysql/conf:/etc/mysql/conf.d"- "./mysql/data:/var/lib/mysql"- "./mysql/init:/docker-entrypoint-initdb.d"networks:- hm-nethmall:build: context: .dockerfile: Dockerfilecontainer_name: hmallports:- "8080:8080"networks:- hm-netdepends_on:- mysqlnginx:image: nginxcontainer_name: nginxports:- "18080:18080"- "18081:18081"volumes:- "./nginx/nginx.conf:/etc/nginx/nginx.conf"- "./nginx/html:/usr/share/nginx/html"depends_on:- hmallnetworks:- hm-net
networks:hm-net:name: hmall
将编写好的yml文件放在root下
(2)基础命令
官方文档:Overview of docker compose CLI | Docker Docs
# 基础语法:
docker compose [OPTIONS] [COMMAND]
类型 | 参数或指令 | 说明 |
---|---|---|
Options | -f | 指定compose文件的路径和名称 |
-p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 | |
Commands | up | 创建并启动所有service容器 |
down | 停止并移除所有容器、网络 | |
ps | 列出所有启动的容器 | |
logs | 查看指定容器的日志 | |
stop | 停止容器 | |
start | 启动容器 | |
restart | 重启容器 | |
top | 查看运行的进程 | |
exec | 在指定的运行中容器中执行命令 |
# 1.进入root目录
cd /root# 2.删除旧容器
docker rm -f $(docker ps -qa)# 3.删除hmall镜像
docker rmi hmall# 4.清空MySQL数据
rm -rf mysql/data# 5.启动所有, -d 参数是后台启动
docker compose up -d# 6.查看镜像
docker compose images# 7.查看容器
docker compose ps# 8.关闭所有容器
docker-compose down
(3)测试
查看springboot的日志,容器是hmall
docker logs -f hmall
打开浏览器,访问:http://yourIp:8080
最后:补充我遇到的一个问题:
在我第二天登录访问http://yourIp:8080的时候发现,进不去,我看了一下springboot的日志。
我觉得应该是没有登录访问被拦截的问题。
下面是解决办法:
访问这个网站:http://192.168.147.130:18080/cart.html或者http://192.168.147.130:18080/
第一个个是前端的登录页面网址,然后用黑马提供的 jack 123 这个账号密码登录,第二个是首页的页面,再去登录就可以了。