提示:以下是本篇文章正文内容,下面案例整理于【黑马程序员】
链接:https://pan.baidu.com/s/1l4Xqxo-eSc5WM8rk-OV1NQ
提取码:bqxq
文章参考笔记:
链接:https://b11et3un53m.feishu.cn/wiki/MWQIw4Zvhil0I5ktPHwcoqZdnec?from=from_copylink
密码:j.N?-+4[
docker命令官方地址:
https://docs.docker.com/engine/reference/commandline/
可以对常用的命令起别名,可以更加简洁,高效的使用命令
# 修改/root/.bashrc文件
vi /root/.bashrc
内容如下:
# .bashrc
# User specific aliases and functions
# 指定rm -i的别名为 rm,在使用rm的时候相当于执行 rm -i
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
执行命令使别名生效
source /root/.bashrc
数据卷命令官方地址:
https://docs.docker.com/engine/reference/commandline/volume_create/
例:如果我们要让Nginx代理我们的静态资源,最好是放到html目录;如果我们要修改Nginx的配置,最好是找到conf下的nginx.conf文件。
但遗憾的是,容器运行的Nginx所有的文件都在容器内部。所以我们必须利用数据卷将两个目录宿主机目录关联,方便我们操作
容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的。而且创建容器的过程中,数据卷会自动创建。
思考: 如果我要部署一个Java项目,把它打包为一个镜像该怎么做呢?
打包镜像步骤:
但需要注意的是:
- 上述步骤中的每一次操作其实都是在生产一些文件(系统运行环境、函数库、配置最终都是磁盘文件),所以镜像就是一堆文件的集合。
- 镜像文件不是随意堆放的,而是按照操作的步骤分层叠加而成,每一层形成的文件都会单独打包并标记一个唯一id,称为Layer(层)。这样,如果我们构建时用到的某些层其他人已经制作过,就可以直接拷贝使用这些层,而不用重复制作。
Dockerfile命令官方地址:
https://docs.docker.com/engine/reference/builder/
由于制作镜像的过程中,需要逐层处理和打包,比较复杂,所以Docker就提供了自动打包镜像的功能。我们只需要将打包的过程,每一层要做的事情用固定的语法写下来,交给Docker去执行即可。
# 查看centos版本
cat /etc/issue
# 或
cat /etc/redhat-release
-----------------------------------------------------
# 查看内核linux版本
cat /proc/version
# 或
uname -a
# 或
uname -r
完整的Dockerfile文件 (包含:操作系统、JDK、JAR、入口脚本)
# 指定基础镜像(可以理解为指定操作系统) 此处根据案例使用ubuntu
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录
ENV JAVA_DIR=/usr/local
#配置容器内时区
ENV TZ=Asia/Shanghai
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
# 拷贝jar包到容器的/tmp/app.jar
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项目的启动命令 其实执行的就是Java -jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
思考: 以后我们会有很多很多java项目需要打包为镜像,他们都需要Linux系统环境、JDK环境这两层,只有上面的3层不同(因为jar包不同)。如果每次制作java镜像都重复制作前两层镜像,是不是很麻烦。所以,就有人提供了基础的系统加JDK环境,我们在此基础上制作java镜像,就可以省去JDK的配置了
简化后的Dockerfile文件 (包含:基础镜像、JAR、入口脚本)
# 基础镜像
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"]
- openjdk:11.0-jre-buste是被人封装好的一个基础的系统,包含基础的操作系统和jdk的环境,所以我们可以只用关注项目jar包和入口脚本即可
- openjdk:11.0-jre-buste 在练习资料里已提供,练习资料里面叫 jdk.tar
docker load -i jdk.tar
# 进入镜像dockerTest
cd /root/dockerTest
# 开始构建 docker-demo:1.0 是我们自定义的镜像的名称和版本,版本不写默认last
docker build -t docker-demo:1.0 .
#????????????????????????????????????????????????????
# 直接指定Dockerfile目录,上面两条命令可以合并成一个
docker build -t docker-demo:1.0 /root/dockerTest
命令解析:
- docker build : 就是构建一个docker镜像
- -t docker-demo:1.0 :-t参数是指定镜像的名称(repository和tag)
- . : 最后的点是指构建时Dockerfile所在路径,由于我们进入了dockerTest目录,所以指定的是 . 代表当前目录,也可以直接指定Dockerfile目录:
docker images
# 1. 创建并运行容器
docker run -d --name dockerTest -p 8080:8080 docker-demo:1.0
# 2. 查看容器-->dps 是因为我使用了命名服务中的命名
dps
# 3. 访问
curl localhost:8080/hello/count
也可以通过浏览器来访问
Docker网络命令官方地址:
https://docs.docker.com/engine/reference/commandline/network/
ip addr
2. 测试容器间的网络是否互通
docker inspect minio
docker inspect oracle11g
docker exec -it oracle11g bash
- 通过上面可以看出,容器虽然是相互隔离且互不影响的,但是容器之间的网络是互通的。这是因为docker在启动的时候会构建一个虚拟网络,当有容器启动的时候,docker会为容器分配一个虚拟ID。
- 容器的网络IP其实是一个虚拟的IP,并不是真实存在的网络设备,外部网络是无法寻址到的,这也意味着外部网络无法直接通过Container-IP 访问到容器,其值并不固定与某一个容器绑定,如果我们在开发时写死某个IP,那么在docker重启的时候容器的IP会发生变化,连接会失败.
为了解决上面的问题,所以需要自定义网络
docker network create 网名名
docker network ls
docker network connect 网络名 容器名 --alias 容器别名
本地目录或文件必须以 / 或 ./开头,如果直接以名字开头,会被识别为数据卷名而非本地目录名
-v mysql:/var/lib/mysql # 会被识别为一个数据卷叫mysql,运行时会自动创建这个数据卷
-v ./mysql:/var/lib/mysql # 会被识别为当前目录下的mysql目录,运行时如果不存在会创建目录
docker run -d --name nginx -p 18080:18080 -p 18081:18081 -v /soft/nginx/nginx.conf:/etc/nginx/nginx.conf -v /soft/nginx/html:/usr/share/nginx/html --network hmall a6bd71f48f68
上传前端页面到【/soft/nginx/html】下,通过映射也被加载到容器内
修改nginx.conf 配置文件进行静态资源代理
至此前端部署完成,通过浏览器进行验证
docker run -d --name mysql5.7 -p 3306:3306 -e TZ=Asia/Shanghai -e MYSQL_ROOT_PASSWORD=123456 -v /soft/mysql/data:/var/lib/mysql -v /soft/mysql/conf:/etc/mysql/conf.d --network hmall c20987f18b13
上传项目jar包,以及Dockerfile文件
对项目jar包进行编译
docker build -t hmall .
9. 运行镜像
# 1. 创建并运行容器,并加入自定义网络
docker run -d --name hmall --network hmall -p 8080:8080 hmall
# 2. 查看容器-->dps 是因为我使用了命名服务中的命名
dps
docker logs -f hmall
DockerCompose命令官方地址:
https://docs.docker.com/compose/reference/
# 指定DockerCompose版本
version: "3"
services:
mysql:
image: mysql
container_name: mysql
ports:
- "3306:3306"
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
volumes:
- "./mysql/conf:/etc/mysql/conf.d"
- "./mysql/data:/var/lib/mysql"
# 使用自定义网络
networks:
- hm-net
# 定义项目jar
hmall:
build:
context: .
# 指定Dockerfile文件位置
dockerfile: Dockerfile
container_name: hmall
ports:
- "8080:8080"
#使用自定义网络
networks:
- hm-net
# 依赖于mysql, 会先去加载mysql再来加载项目jar
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"
# 依赖于mysql, 会先去加载mysql再来加载项目jar
depends_on:
- hmall
#使用自定义网络
networks:
- hm-net
#自定义网络
networks:
hm-net:
name: hmall
上传项目jar包,Dockerfile文件以及写好的DockerCompose文件,并创建挂载目录
一键启动
docker-compose up -d
5. 查看镜像
6. 访问,验证
前端:
后端:
7. 停止docker-compose
docker-compose down
docker-compose 2.23.3版本下载
链接:https://pan.baidu.com/s/115LwBXm4taXCiFK190Xykw
提取码:u9tc
https://github.com/docker/compose/releases
mv docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose --version