准备环境
Linux环境搭建
搭建Linux环境
安装VMware
VMware只能安装一个,卸载旧版本的VMware时若在控制面板卸载还要看看VMware的安装目录是否有旧数据,旧数据也要删掉。还要清理注册表。
下载地址:https://www.vmware.com/products/workstation-player/workstation-player-evaluation.html.html.html
创建虚拟机
在VMware《主页》界面中点击《创建新的虚拟机》按钮,选用经典类型的配置即可。
选择好页面中选择准备好的ISO文件,这里使用的是CentOS-7-x86_64-DVD-1810,可以在清华大小的镜像里下载(地址:https://mirrors.tuna.tsinghua.edu.cn/centos-vault/7.6.1810/isos/x86_64,下载其中的4.3Gib的CentOS-7-x86_64-DVD-1810.iso即可);
然后填写个性化信息:
设置虚拟机名称以及安装位置:
填写虚拟机磁盘大小。这里建议给大一点,否则将来不够用调整起来麻烦。而且这里设置大小并不是立刻占用这么多,而是设置一个上限:
在下一步的自定义硬件设置虚拟机硬件,建议CPU给到4核,内存给到8G:
点击完成后即可完成。
安装Linux
搭建好虚拟环境后,点击开启此虚拟机。启动后需要选择安装菜单,将鼠标移入黑窗口中后,将无法再使用鼠标,需要按上下键选择菜单。选中Install Centos 7 后按下回车:
设置语言,配置网络(可选)。网络页面可以修改主机名为自己喜欢的主机名,不要出现中文和特殊字符,建议用localhost设置详细网络信息。
完成后点击右下角的Begin InstallLation即可开始安装,过程可能稍微长一些。
设置快照
在虚拟机安装完成后,最好立刻设置一个快照,这样一旦将来虚拟机出现问题,可以快速恢复。
关闭虚拟机 设置快照
假如以后虚拟机文件受损,需要恢复到初识状态的话,可以选中要恢复的快照,点击转到即可:
SSH客户端
在VMware界面中操作虚拟机非常不友好,所以一般使用专门的SSH客户端。市面上常见的有:
Xshell:个人免费,商业收费,之前爆出过有隐藏后门。不推荐
Finshell:基础功能免费,高级功能收费,基于Java,内存占用较高(在1个G左右)。
MobarXterm:基础功能免费、高级功能收费。开源、功能强大、内存占用低(只有10m左右),但是界面不太漂亮。
Finshell:
Finshell可以试着从官网下载,但可能不太好下。也可以找有Finshell安装包的人要从网上找。
Finshell打开后的界面:
下载后要连接Linux系统,使用SSH连接
填写名称(连接的名称)、主机ip(Linux的)、用户名和密码
建立好连接后之后都可以快速连接:
连接成功后:
如果要把在电脑其它界面复制的内容粘贴到Finshell需要在Finshell中用CTRL+SHIFT+V快捷键而不是CTRL+V,在Finshell复杂则需要CTRL+SHIFT+C
安装Docker
如果系统中已经存在旧的Docker,可以先卸载再安装新的,旧的可以用就不必了。
安装Docker
卸载Docker:
bash
yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
Docker在安装前需要先配置Docker的yum库( 这里使用阿里的yum源):
备份yum源:mv /etc/yum.repo.d/CentOS-Base.repo /etc/yum.repo.d/CentOS-Base.repo.backup
使用阿里云更新yum源:curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
清除yum:yum clean all
更新缓存:yum makecache
安装成功后,执行命令,配置Docker的yum源(由于国内访问不到docker官方镜像,可以通过aliyun的源来完成):
sudo 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
bash
# 启动Docker
systemctl start docker
# 停止Docker
systemctl stop docker
# 重启
systemctl restart docker
# 设置开机自启
systemctl enable docker
# 执行docker ps命令,如果不报错,说明安装启动成功
docker ps
配置镜像加速
可以配置阿里云的镜像:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
具体命令如下:
bash
# 创建目录
mkdir -p /etc/docker
# 复制内容,注意把其中的镜像加速地址改成自己的
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}
EOF
# 重新加载配置
systemctl daemon-reload
# 重启Docker
systemctl restart docker
Docker快速入门
部署MySQL为例
使用Docker安装只需要在命令行输入下面的命令即可:
bash
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网站或者软件的官方网站中都能找到。
使用Docker下载的不是安装包,而是镜像。 镜像中不仅包含了MySQL本身,还包含了其运行所需要的环境、配置、系统级函数库。因此它在运行时就有自己独立的环境,就可以跨系统运行,也不需要手动再次配置环境。这套独立运行的隔离环境称为容器。
Docker官方提供了一个专门管理、存储镜像的网站,并对外开放了镜像上传、下载的权利。Docker官方提供了一些基础镜像,然后各大软件公司又在基础镜像基础上,制作了自家软件的镜像,全部都存放在这个网站。这个网站就成了Docker镜像交流的社区:https://hub.docker.com/
像这种提供存储、管理Docker镜像的服务器,被称为DockerRegistry,可以翻译为镜像仓库。DockerHub网站是官方仓库,阿里云、华为云会提供一些第三方仓库,我们也可以自己搭建私有的镜像仓库。
官方仓库在国外,下载速度较慢,一般我们都会使用第三方仓库提供的镜像加速功能,提高下载速度。而企业内部的机密项目,往往会采用私有镜像仓库。
总之,镜像的来源有两种:
基于官方基础镜像自己制作
直接去DockerRegistry下载
Docer基础
常见指令
命令 | 说明 |
---|---|
docker pull | 拉取镜像 |
docker push | 推送镜像到DockerRegistry |
docker images | 查看本地镜像 |
docker rmi | 删除本地镜像 |
docker run | 创建并运行容器(不能重复创建) |
docker stop | 停止指定容器。停止的是容器内进程,并非容器 |
docker start | 启动指定容器 |
docker restart | 重新启动容器 |
docker rm | 删除指定容器 |
docker ps | 查看容器 |
docker logs | 查看容器运行日志 |
docker exec | 进入容器 |
docker save | 保存镜像到本地压缩文件 |
docker load | 加载本地压缩文件到镜像 |
docker inspect | 查看容器详细信息 |
以Nginx为例:
bash
# 第1步,去DockerHub查看nginx镜像仓库及相关信息
# 第2步,拉取Nginx镜像
docker pull nginx
# 第3步,查看镜像
docker images
# 结果如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 16 months ago 141MB
mysql latest 3218b38490ce 17 months ago 516MB
# 第4步,创建并允许Nginx容器
docker run -d --name nginx -p 80:80 nginx
# 第5步,查看运行中容器
docker ps
# 也可以加格式化方式访问,格式会更加清爽
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第6步,访问网页,地址:http://虚拟机地址
# 第7步,停止容器
docker stop nginx
# 第8步,查看所有容器
docker ps -a --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第9步,再次启动nginx容器
docker start nginx
# 第10步,再次查看容器
docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
# 第11步,查看容器详细信息
docker inspect nginx
# 第12步,进入容器,查看容器内目录
docker exec -it nginx bash
# 或者,可以进入MySQL
docker exec -it mysql mysql -uroot -p
# 第13步,删除容器
docker rm nginx
# 发现无法删除,因为容器运行中,强制删除容器
docker rm -f nginx
默认情况下,每次重启虚拟机我们都需要手动启动Docker和Docker中的容器。通过命令可以实现开机自启:
bash
# Docker开机自启
systemctl enable docker
# Docker容器开机自启
docker update --restart=always [容器名/容器id]
可以给常用Docker命令起别名,方便访问:
bash
# 修改/root/.bashrc文件
vi /root/.bashrc
内容如下:
# .bashrc
# User specific aliases and functions
alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
alias dis='docker images'
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
数据卷
容器是隔离环境,容器内程序的文件、配置、运行时产生的容器都在容器内部,读写容器内的文件需要用到数据卷。
数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。
/var/lib/docker/volumes这个目录就是默认的存放所有容器数据卷的目录,其下再根据数据卷名称创建新目录,格式为/数据卷名/_data。
在执行docker run命令时,使用 -v 数据卷 : 容器内目录 可以完成数据卷挂载。
以nginx的html目录挂载为例:
bash
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
当创建容器时,如果挂载了数据卷且数据卷不存在,会自动创建数据卷。自动创建的数据卷其名称是随机生成的,其数据卷称为匿名数据卷。
容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
数据卷的相关命令:
命令 | 说明 |
---|---|
docker volume create | 创建数据卷 |
docker volume ls | 查看所有数据卷 |
docker volume rm | 删除指定数据卷 |
docker volume inspect | 查看某个数据卷的详情 |
docker volume prune | 清除数据卷 |
数据卷的目录结构较深,如果我们去操作数据卷目录会不太方便。在很多情况下,我们会直接将容器目录与宿主机指定目录挂载。挂载语法与数据卷类似:
bash
# 挂载本地目录
-v 本地目录:容器内目录
# 挂载本地文件
-v 本地文件:容器内文件
本地目录必须以"/"或 "./" 开头,如果直接以名称开头,会被识别为数据卷而非本地目录
bash
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
以挂载mysql数据库为例:
bash
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
镜像
镜像本质是依次准备好程序运行的基础环境、依赖、应用本身、运行配置等文件,并且打包而成的。打包一个Java应用镜像需要分多个步骤完成,镜像文件按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一id,称为Layer(层)。这样,如果构建时用到的某些层已经制作过,就可以直接拷贝使用这些层,而不用重复制作。
Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。这种记录镜像结构的文件就称为Dockerfile。
其对应的语法可以参考官方文档:https://docs.docker.com/engine/reference/builder/
常用语法:
指令 | 说明 | 示例 |
---|---|---|
FROM | 指定基础镜像 | FROM centos:6 |
ENV | 设置环境变量,可在后面指令使用 | ENV key value |
COPY | 拷贝本地文件到镜像的指定目录 | COPY ./xx.jar /tmp/app.jar |
RUN | 执行Linux的shell命令,一般是安装过程的命令 | RUN yum install gcc |
EXPOSE | 指定容器运行时监听的端口,是给镜像使用者看的 | EXPOSE 8080 |
ENTRYPOINT | 镜像中应用的启动命令,容器运行时调用 | ENTRYPOINT java -jar xx.jar |
如果要基于Ubuntu镜像来构建一个Java应用,其Dockerfile内容如下:
bash
# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 设定时区
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 安装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 8080
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
但有人提供了基础的系统加JDK环境,在此基础上制作java镜像,可以省去JDK的配置:
bash
# 基础镜像
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"]
如若在root/demo目录下有一个docker-demo.jar包以及Dockerfile,构建镜像步骤如下:
bash
# 进入镜像目录
cd /root/demo
# 开始构建
docker build -t docker-demo:1.0 .
docker build : 就是构建一个docker镜像
-t docker-demo:1.0 :-t参数是指定镜像的名称(repository和tag)
. : 最后的点是指构建时Dockerfile所在路径,由于我们进入了demo目录,所以指定的是.代表当前目录,也可以直接指定Dockerfile目录
网络
容器的网络IP是一个虚拟的IP,并不固定与某一个容器绑定,如果我们在开发时写死某个IP,而在部署时很可能容器的IP会发生变化导致连接失败。
可以借助于docker的自定义网络功能来解决这个问题,加入自定义网络的容器可以通过容器名互相访问,不过只有在同一个自定义网络中的容器可以通过别名互相访问。
在自定义网络中,可以给容器起多个别名,默认的别名是容器名本身。
常见命令有:
命令 | 说明 |
---|---|
docker network create | 创建一个网络 |
docker network ls | 查看所有网络 |
docker network rm | 删除指定网络 |
docker network prune | 清除未使用的网络 |
docker network connect | 使指定容器连接加入某网络 |
docker network disconnect | 使指定容器连接离开某网络 |
docker network inspect | 查看网络详细信息 |
bash
# 创建一个hmall网络
docker network create hmall
# 可以查看网络
docker network ls
# 让dd和mysql都加入该网络,在加入网络时可以通过--alias给容器起别名
# mysql容器,指定别名为db,另外每一个容器都有一个别名是容器名
docker network connect hmall mysql --alias db
# db容器
docker network connect hmall dd
官方文档:https://docs.docker.com/engine/reference/commandline/network/
项目部署
以黑马商城为例子,内容可从黑马程序员官网获取。(连接)
项目说明:
hmall:商城的后端代码
hmall-portal:商城用户端的前端代码
hmall-admin:商城管理端的前端代码
部署的容器及端口说明:
项目 | 容器名 | 端口 | 备注 |
---|---|---|---|
hmall | hmall | 8080 | 黑马商城后端API入口 |
hmall-portal | nginx | 18080 | 黑马商城用户端入口 |
hmall-admin | nginx | 18081 | 黑马商城管理端入口 |
mysql | mysql | 3306 | 数据库 |
部署Java项目
部署hmall项目中的hm-service,将项目打包。将hm-service目录下的Dockerfile和hm-service/target目录下的hm-service.jar一起上传到虚拟机的root目录:
部署项目:
bash
# 构建项目镜像,不指定tag,则默认为latest
docker build -t hmall .
# 创建并运行容器,并通过--network将其加入hmall网络,这样可以通过容器名访问mysql
docker run -d --name hmall --network hmall -p 8080:8080 hmall
部署前端
hmall-portal和hmall-admin是前端代码,需要基于nginx部署。
nginx的html目录是nginx的静态资源目录,需要把hmall-portal以及hmall-admin都复制进去
nginx.conf是nginx的配置文件,主要是完成对html下的两个静态资源目录做代理
将整个nginx目录上传到虚拟机的/root目录下:
然后创建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
bash
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
DockerCompose
Docker Compose可以实现多个相互关联的Docker容器的快速部署。通过一个单独的docker-compose.yml 模板文件(YAML 格式)来定义一组相关联的应用容器。
docker run 参数与docker compose指令对应关系:
docker run 参数 | docker compose 指令 | 说明 |
---|---|---|
--name | container_name | 容器名称 |
-p | ports | 端口映射 |
-e | environment | 环境变量 |
-v | volumes | 数据卷配置 |
--network | networks | 网络 |
黑马商城部署文件:
bash
version: "3.8"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
- "./mysql/init:/docker-entrypoint-initdb.d"
networks:
- hm-net
hmall:
build:
context: .
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
networks:
- hm-net
depends_on:
- mysql
nginx:
image: nginx
container_name: nginx
ports:
- "18080:18080"
- "18081:18081"
volumes:
- "./nginx/nginx.conf:/etc/nginx/nginx.conf"
- "./nginx/html:/usr/share/nginx/html"
depends_on:
- hmall
networks:
- hm-net
networks:
hm-net:
name: hmall
部署项目基本语法:
docker compose [OPTIONS] [COMMAND]
其中,OPTIONS和COMMAND都是可选参数,比较常见的有:
类型 | 参数或指令 | 说明 |
---|---|---|
Options | -f | 指定compose文件的路径和名称 |
Options | -p | 指定project名称。project就是当前compose文件中设置的多个service的集合,是逻辑概念 |
Commands | up | 创建并启动所有service容器 |
Commands | down | 停止并移除所有容器、网络 |
Commands | ps | 列出所有启动的容器 |
Commands | logs | 查看指定容器的日志 |
Commands | stop | 停止容器 |
Commands | start | 启动容器 |
Commands | restart | 重启容器 |
Commands | top | 查看运行的进程 |
Commands | exec | 在指定的运行中容器中执行命令 |
bash
# 启动所有, -d 参数是后台启动
docker compose up -d