Docker入门
CentOS 7(使用 yum 进行安装)
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3
sudo sed -i 's+download.docker.com+mirrors.aliyun.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
# Step 4: 更新并安装Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 5: 设置docker开机自启
sudo systemctl enable docker
# Step 6: 开启Docker服务
sudo service docker start
# 注意:
# 官方软件源默认启用了最新的软件,您可以通过编辑软件源的方式获取各个版本的软件包。例如官方并没有将测试版本的软件源置为可用,您可以通过以下方式开启。同理可以开启各种测试版本等。
# vim /etc/yum.repos.d/docker-ce.repo
# 将[docker-ce-test]下方的enabled=0修改为enabled=1
#
# 安装指定版本的Docker-CE:
# Step 1: 查找Docker-CE的版本:
# yum list docker-ce.x86_64 --showduplicates | sort -r
# Loading mirror speeds from cached hostfile
# Loaded plugins: branch, fastestmirror, langpacks
# docker-ce.x86_64 17.03.1.ce-1.el7.centos docker-ce-stable
# docker-ce.x86_64 17.03.1.ce-1.el7.centos @docker-ce-stable
# docker-ce.x86_64 17.03.0.ce-1.el7.centos docker-ce-stable
# Available Packages
# Step2: 安装指定版本的Docker-CE: (VERSION例如上面的17.03.0.ce.1-1.el7.centos)
# sudo yum -y install docker-ce-[VERSION]
Docker 进程相关命令
- 启动docker服务:
systemctl start docker
- 停止docker服务:
systemctl stop docker
- 重启docker服务:
systemctl restart docker
- 查看docker服务状态:
systemctl status docker
- 设置开机启动docker服务:
systemctl enable docker
Docker 镜像相关命令
- 查看镜像: 查看本地所有的镜像
docker images
# 查看所用镜像的id
docker images –q
- 搜索镜像:从网络中查找需要的镜像
docker search 镜像名称
- 拉取镜像:从Docker仓库下载镜像到本地,镜像名称格式为 名称:版本号,如果版本号不指定则是最新的版本。 如果不知道镜像版本,可以去docker hub 搜索对应镜像查看。
docker pull 镜像名称
- 删除镜像: 删除本地镜像
# 删除指定本地镜像
docker rmi 镜像id
# 删除所有本地镜像
docker rmi `docker images -q`
Docker 容器相关命令
- 查看容器
# 查看正在运行的容器
docker ps
# 查看所有容器
docker ps –a
- 创建并启动容器
docker run 参数
- 参数说明:
-i:保持容器运行。通常与 -t 同时使用。加入it这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭。
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用。
-d:以守护(后台)模式运行容器。创建一个容器在后台运行,需要使用docker exec 进入容器。退出后,容器不会关闭。
-it: 创建的容器一般称为交互式容器,-id 创建的容器一般称为守护式容器
--name:为创建的容器命名。
-p: 端口主机端口与容器端口的映射关系,如配置-p 8888:80代表开放容器端口80并将主机端口8888映射到容器的80端口
-P:表示开放容器全部端口,并将主机的端口随机与容器端口做映射
--rm: 表示容器停止后自动删除容器
–restart:重启策略,always意外关闭之后就会自动重启(开机启动),on-failure可以设置重启次数(on-failure:3表示重启3次),默认no即不会重启
--net:配置网卡
- 进入容器
# 退出容器,容器不会关闭
docker exec 参数
# 进入nginx并打开终端
docker exec -it nginx /bin/bash
- 停止容器
docker stop 容器名称
- 启动容器
docker start 容器名称
- 删除容器:如果容器是运行状态则删除失败,需要停止容器才能删除
docker rm 容器名称
- 查看容器信息
docker inspect 容器名称
Docker 容器的数据卷
什么是数据卷
- 数据卷是宿主机中的一个目录或文件
- 当容器目录和数据卷目录绑定后,对方的修改会立即同步
- 一个数据卷可以被多个容器同时挂载
- 一个容器也可以被挂载多个数据卷
有什么用
- 容器数据持久化
- 外部机器和容器间接通信
- 容器之间数据交换
配置数据卷
- 创建启动容器时,使用 –v 参数 设置数据卷
docker run ... –v 宿主机目录(文件):容器内目录(文件) ...
- 注意事项:
- 目录必须是绝对路径
- 如果目录不存在,会自动创建
- 可以挂载多个数据卷
以nginx为例
docker run \
-p 8888:80 \
--name nginx \
-v /Users/wandaren/develop/docker-nginx/conf/nginx.conf:/etc/nginx/nginx.conf \
-v /Users/wandaren/develop/docker-nginx/conf/conf.d:/etc/nginx/conf.d \
-v /Users/wandaren/develop/docker-nginx/log:/var/log/nginx \
-v /Users/wandaren/develop/docker-nginx/html:/usr/share/nginx/html \
-d nginx
# 挂载nginx.conf配置文件
-v /Users/wandaren/develop/docker-nginx/conf/nginx.conf:/etc/nginx/nginx.conf
# 挂载nginx配置文件
-v /Users/wandaren/develop/docker-nginx/conf/conf.d:/etc/nginx/conf.d
# 挂载nginx日志文件
-v /Users/wandaren/develop/docker-nginx/log:/var/log/nginx
# 挂载nginx内容
-v /Users/wandaren/develop/docker-nginx/html:/usr/share/nginx/html
\ shell 命令换行
网络Network
是什么
- 是Docker对容器网络隔高的一项技术,提供了多种不同的模式供用户使用,选择不同的网络模式来实现容器网络的互通以及彻底的隔离。
为什么需要
- 容器间的风络隔离
- 实现部分容器之间的网络共享
- 管理多个子网下容的ip
能干什么
- 提供了多种模式,可以定制化的为每个容器指定不同的网络
- 自定义网络模式,划分不同的子网以及网关、dns等配置
- 网络互通
- 实现不同子网之间的网络互通
- 基于容器名(主机名)的方式在网络内访问
Dockerfile
Docker 镜像原理
- 进程调度子系统
- 进程通信子系统
- 内存管理子系统
- 设备管理子系统
- 文件管理子系统
- 网络通信子系统
- 作业控制子系统
操作系统组成部分:
Linux文件系统由bootfs和rootfs两部分组成
- bootfs:包含bootloader(引导加载程序)和 kernel(内核)
- rootfs: root文件系统,包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc等标准目录和文件
- 不同的linux发行版,bootfs基本一样,而rootfs不同,如ubuntu,centos等
Docker镜像是由特殊的文件系统叠加而成
- 最底端是 bootfs,并使用宿主机的bootfs
- 第二层是 root文件系统rootfs,称为base image
- 然后再往上可以叠加其他的镜像文件
- 统一文件系统(Union File System)技术能够将不同的层整合成一个文件系统,为这些层提供了一个统一的视角 ,这样就隐藏了多层的存在,在用户的角度看来,只存在一个文件系统。
- 一个镜像可以放在另一个镜像的上面。位于下面的镜像称 为父镜像,最底部的镜像成为基础镜像。
- 当从一个镜像启动容器时,Docker会在最顶层加载一个读 写文件系统作为容器
思考:
Docker 镜像本质是什么?
- 是一个分层文件系统
Docker 中一个centos镜像为什么只有200MB,而一个centos操作系统的iso文件要几个个G?
- Centos的iso镜像文件包含bootfs和rootfs,而docker的centos镜像复用操作系统的bootfs,只有rootfs和其他镜像层
Docker 中一个tomcat镜像为什么有500MB,而一个tomcat安装包只有70多MB?
- 由于docker中镜像是分层的,tomcat虽然只有70多MB,但他需要依赖于父镜像和基础镜像,所有整个对外暴露的
tomcat镜像大小500多MB
Docker 镜像如何制作?
容器转为镜像
docker commit 容器id 镜像名称:版本号
docker save -o 压缩文件名称 镜像名称:版本号
docker load –i 压缩文件名称
dockerfile
- Dockerfile 是一个文本文件
- 包含了一条条的指令
- 每一条指令构建一层,基于基础镜像,最终构建出一个新的镜像
- 对于开发人员:可以为开发团队提供一个完全一致的开发环境
- 对于测试人员:可以直接拿开发时所构建的镜像或者通过Dockerfile文件构建一个新的镜像开始工作了
- 对于运维人员:在部署时,可以实现应用的无缝移植
案例
使用commit构建镜像,修改nginx默认首页内容
# 启动一个临时容器
docker run --rm -d -p 80:80 --name n1 nginx
# 进入临时容器
docker exec -it n1 /bin/bash
# 进入nginx挂载目录
cd /usr/share/nginx/html/
# 修改index.html内容
echo '<h1>hello docker</h1>' > index.html
# 使用commit构建镜像
docker commit -a "作者" -m "描述" n1 mynginx:1
# 查看镜像
docker images
# 运行新镜像
docker run -d --rm -p 80:80 --name n2 mynginx:1
bulid常用命令
#1,先指定当前镜像的基础镜像是什么
FROM openjdk:8
# 2,描述这个镜像的作者,以及联系方式 (可选)
MAINTAINER test<xxx@qq.com>
# 3,镜像的标签信息 (可选 )
LABEL version="1."LABEL description="这是我的第一个 Dockerfile"
# 4,环境变量配置
ENV JAVA ENV dev
ENV APP NAME test-dockerfile
# ENV JAVA ENVdev APP NAME=test-dockerfile
#5,在构建镜像时,需要执行的 shell 命令
RUN Is -al
RUN mkdir /www/dockerfile/test
# 6,将主机中的指定文件复制到容器的目标位置,可以简单理解为 cp 命令
# ADD /www/test/index.html /www/server
ADD ["/www/test","/www/server"]
#7,设置容器中的工作目录,如果该目录不存在,那么会自己创建
WORKDIR /app
# 在设置完工作目录后,执行 pwd 命令,打印的目录就是 /app
RUN pwd
# 8,镜像数据卷绑定,将主机中的指定目录挂载到容器中
VOLUME ["/www/test"]
# 9,设置容器启动后要暴露的端口
EXPOSE 8080/tcp
# CMD 和 ENTRYPOINT 选择其一即可,作用是描述镜像构建完成后,启动容器时默认执行的脚本
# CMD ping 127.0.0.1
# CMD ["sh",'-c","ping 127.0.0.1"]
# ENTRYPONINT ping 127.9.0.1
ENTRYPOINT "sh","-c","ping 127.0.0.1"
拓展命令
-
ARG设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg
= 来指定参数 -
HEALTHCHECK 容器健康状况检查命令
CMD与ENTRYPOINT的区别 相同点:
-
在整个 Dockerfile 中只能设置一次,如果写了多次则只有量后一次生效
不同点:
- ENTRYPOINT 不会被运行容器时指定的命令所覆盖,而CMD 会被覆盖
- 如果同时设置了这两个指令,且 CMD 仅仅是选项而不是参数,CMD 中的内容会作为 ETRYPQINI 的参数(一股不这么)
- 如果两个都是完整命令,那么只会执行最后一条
#### bulid构建springboot容器并运行
##### 以jar的形式
一个简单的springboot项目,端口默认8080,提供了一个对外访问接口/hello
![image.png](https://cdn.nlark.com/yuque/0/2023/png/8364180/1691635749768-fcca8620-f2c1-4634-afd1-258fec3cf7da.png#averageHue=%231e1f22&clientId=u1e83b879-5788-4&from=paste&height=455&id=u52aa12dc&originHeight=910&originWidth=1774&originalType=binary&ratio=2&rotation=0&showTitle=false&size=176730&status=done&style=none&taskId=uaa3cee78-ae0f-41df-b397-34fb20dd4da&title=&width=887)
```java
package com.example.demo.contorller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Description TODO
* @Version 1.0.0
* @Date 2023/8/10
* @Author wandaren
*/
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "hello docker springboot!";
}
}
# 创建目录
mkdir springboot-docker
cd springboot-docker
# 创建Dockerfile
touch Dockerfile
# 将springboot启动jar拷贝到springboot-docker目录下,jar包与Dockerfile放在同级目录
编写Dockerfile文件内容如下
# 关联基础依赖
FROM openjdk:17
# 将项目jar包拷贝到容器中
ADD *.jar /app.jar
# 配置项目环境变量
ENV APP_OPTS=""
# JVM环境变量
ENV JVM_OPTS="-Duser.tomezone=Asia/Shanghai -Xms128m -Xmx128m"
# 暴露端口,与项目端口对应
EXPOSE 8080
# 设置启动时的命令
ENTRYPOINT ["sh","-c","java $JVM_OPTS -jar /app.jar $APP_OPTS"]
构建与测试
# 最后一个参数为Dockerfile文件路径目录(springboot-docker),.表示同级目录下的Dockerfile
docker build -t springboot-docker:1.0.0 .
# 运行
docker run --rm -d -p 8888:8080 springboot-docker:1.0.0
# 访问http://localhost:8888/hello即可
以war的形式部署到tomcat
- 使用的是springboot3.1.2,tomcat10.1.11
改造springboot项目
- 修改打包方式为war,排除springboot自带的tomcat
<!-- 修改打包方式为war -->
<packaging>war</packaging>
<!-- 排除springboot自带的tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
- 添加servle-api或者tomcat依赖,二选一即可
<!-- servlet依赖 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>6.0.0</version>
<scope>provided</scope>
</dependency>
<!-- 这个依赖让你能够在程序入口类:xxxAppAplication中直接执行main方法启动tomcat -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!-- 但是这里一定要设置为provided -->
<scope>provided</scope>
</dependency>
- 修改启动类,继承SpringBootServletInitializer重写configure方法
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
public class DemoApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
// 注意这里要指向原先用main方法执行的Application启动类
return builder.sources(DemoApplication.class);
}
}
编写Dockerfile,将war拷贝到Dockerfile同级目录下
FROM tomcat:10.1.11
WORKDIR /usr/local/tomcat/webapps
# 拷贝到tomcat并改为ROOT解压之后更方便使用(访问可以不带路径)
ADD *.war ROOT.war
ENTRYPOINT ["sh","-c","../bin/catalina.sh run"]
- 构建与运行
# 最后一个参数为Dockerfile文件路径目录(/Users/wandaren/tomcat-docker),会自动查找Dockerfile文件
docker build -t javaweb /Users/wandaren/tomcat-docker
docker run -d --rm -P javaweb