其实就是对进程的封装,使得它与其他进程独立,并且独立于宿主,也称为容器
Docker是对容器的封装
那他与传统的虚拟机有什么区别呢?
传统虚拟需要虚拟出一套硬件,在其上面运行一个完整的操作系统,在这个系统上运行所需应用进程;而容器内的应用程序直接运行在宿主的内核,容器内没有直接点内核,也没有硬件虚拟。所以容器要比传统的虚拟机更加轻便。
那它有什么优势呢?
高效的利用系统的资源
快速的启动时间
一致的运行环境
持续交付和部署
轻松的迁移、维护和扩展
三个要素是啥?
镜像、容器、仓库
一、Docker概述
1.1 Docker 为什么出现?
解决环境差异问题:开发、测试、生产环境不一致,导致应用部署困难。
提高资源利用率:传统虚拟机资源占用大,Docker容器更轻量,能更高效地利用硬件资源。
1.2 Docker历史
2013年,Docker项目启动。
2014年,Docker 1.0版本发布,标志着Docker技术的成熟。
1.3 能做什么
应用打包:将应用及其依赖打包成一个容器,确保在任何环境下都能正常运行。
环境隔离:为每个应用提供独立的运行环境,避免依赖冲突。
快速部署:容器启动迅速,能快速部署应用。
持续集成与交付:与CI/CD流程结合,实现自动化测试和部署。
二、Docker安装
2.1 基本组成
Docker客户端:用户通过命令行工具与Docker守护进程通信。
Docker守护进程:负责构建、运行和管理容器。
Docker镜像:只读的模板,包含应用程序及其依赖。
Docker容器:镜像的运行实例,提供隔离的运行环境。
Docker仓库:存储和管理Docker镜像的地方。
2.2 安装Docker
Linux:使用包管理工具安装,如
apt
或yum
。Windows:安装Docker Desktop for Windows。
Mac:安装Docker Desktop for Mac。
2.3 阿里云镜像加速
配置镜像加速可以提高镜像下载速度,特别是在国内网络环境下。
配置方法:在Docker守护进程配置文件中添加镜像加速地址。
2.4 回顾hello-world流程
拉取
hello-world
镜像:docker pull hello-world
运行容器:
docker run hello-world
2.5 底层原理
Docker是怎么工作的?
Docker利用Linux内核的Cgroups和NameSpace技术,对进程进行封装隔离。
容器共享宿主机的操作系统内核,但彼此隔离。
Docker为什么比VM(虚拟机)快?
虚拟机需要完整的操作系统,占用大量资源。
Docker容器共享宿主机的操作系统,资源占用少,启动速度快。
三、Docker的常用命令
3.1 帮助命令
docker --help
:查看所有可用命令。
3.2 镜像命令
docker images
:列出本地镜像。docker search <镜像名>
:在Docker Hub搜索镜像。docker pull <镜像名>
:拉取镜像。docker rmi <镜像ID>
:删除镜像。
3.3 容器命令
docker run <镜像名>
:创建并运行容器。docker ps
:列出正在运行的容器。docker ps -a
:列出所有容器(包括停止的)。docker stop <容器名>
:停止容器。docker start <容器名>
:启动容器。docker rm <容器名>
:删除容器。docker exec -it <容器名> /bin/bash
:进入容器。
3.4 其他命令
docker logs <容器名>
:查看容器日志。docker cp <容器名>:<路径> <本地路径>
:从容器复制文件到主机。docker inspect <容器名>
:查看容器详细信息。
四、Docker镜像
4.1 镜像是什么
镜像是一个只读的模板,包含应用程序及其依赖。
镜像由多层文件系统组成,每层代表一个文件系统的变更。
4.2 镜像加速原理
UnionFS(联合文件系统):允许多个文件系统(层)叠加在一起,形成一个统一的文件系统视图。
Docker 镜像加载原型:镜像的每一层都是只读的,当容器启动时,Docker会在镜像顶部添加一个可写的层,用于存储容器运行时的变更。
4.3 分层理解
镜像的分层结构使得镜像共享和复用更加高效。
多个容器可以共享同一镜像的底层,减少存储空间。
4.4 commit镜像
docker commit <容器名> <新镜像名>
:将容器的更改提交为新的镜像。
五、Docker网络
5.1 网络类型
Bridge模式:默认网络,容器通过
docker0
网卡连接到宿主机。Host模式:容器直接使用宿主机的网络栈,没有网络隔离。
Overlay模式:用于多宿主机的容器网络通信。
None模式:容器没有网络。
5.2 网络命令
docker network create <网络名>
:创建自定义网络。docker network ls
:列出所有网络。docker network rm <网络名>
:删除网络。docker network connect <网络名> <容器名>
:将容器连接到网络。docker network disconnect <网络名> <容器名>
:将容器从网络断开。
六、Docker Compose
6.1 作用
Docker Compose用于定义和管理多容器应用,通过
docker-compose.yml
文件配置服务、网络和卷。
6.2 常用命令
docker-compose up
:创建并启动所有服务。docker-compose down
:停止并删除所有服务、网络和卷。docker-compose ps
:列出所有服务的状态。
七、Docker实际应用案例
7.1 运行Nginx服务
bash复制
docker run -d -p 80:80 --name mynginx nginx
7.2 搭建Redis主从同步集群
bash复制
# 主节点
docker run -d -p 6379:6379 \
-v /app/rd1:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=master \
-e REDIS_PASSWORD=123456 \
--network mynet --name redis01 \
bitnami/redis
# 从节点
docker run -d -p 6380:6379 \
-v /app/rd2:/bitnami/redis/data \
-e REDIS_REPLICATION_MODE=slave \
-e REDIS_MASTER_HOST=redis01 \
-e REDIS_MASTER_PORT_NUMBER=6379 \
-e REDIS_MASTER_PASSWORD=123456 \
-e REDIS_PASSWORD=123456 \
--network mynet --name redis02 \
bitnami/redis
八、Docker在Java开发中的应用
8.1 部署Java应用
将Java应用打包成Docker镜像,便于在不同环境中部署。
使用
Dockerfile
定义Java应用的运行环境和启动命令。
8.2 示例:部署Spring Boot应用
dockerfile复制
# 使用官方Java镜像作为基础镜像
FROM openjdk:11-jre-slim
# 设置工作目录
WORKDIR /app
# 复制应用JAR文件到容器
COPY target/myapp.jar /app/myapp.jar
# 暴露应用端口
EXPOSE 8080
# 启动应用
CMD ["java", "-jar", "myapp.jar"]
通过以上内容的学习,你可以快速掌握Docker的基础知识和实际应用,为Java开发面试做好准备。
九、Docker在Java开发中的应用
一、基础概念
Docker:Docker是一个开源的平台,用于开发、部署和运行应用,可通过容器轻松打包应用及其依赖。
容器:容器是一个标准的软件单元,它将代码及其所有依赖打包在一起,使Java应用在几乎任何计算环境中都能快速、可靠地运行。
镜像:镜像是一个轻量级、独立、可执行的打包格式,包含了运行应用所需的所有内容,包括Java运行环境、代码、库。
二、Java应用的Docker容器化
2.1 Dockerfile 编写
要容器化一个Java应用,首先需要编写一个 Dockerfile
,它定义了如何构建Docker镜像。以下是一个简单的 Dockerfile
示例,用于Java应用:
dockerfile复制
# 使用OpenJDK基础镜像
FROM openjdk:11-jre-slim
# 设置工作目录
WORKDIR /app
# 复制应用Jar文件到容器
COPY target/my-java-app.jar /app/my-java-app.jar
# 暴露应用端口
EXPOSE 8080
# 执行Java应用命令
CMD ["java", "-jar", "/app/my-java-app.jar"]
2.2 构建 Docker 镜像
在 Dockerfile
编写完成后,可以使用Docker命令行来构建镜像:
bash复制
docker build -t my-java-app .
此命令会将当前目录下的 Dockerfile
构建成一个名为 my-java-app
的Docker镜像。
2.3 运行 Docker 容器
构建好镜像后,接下来的步骤是运行容器:
bash复制
docker run -d -p 8080:8080 --name my-running-app my-java-app
该命令通过Docker镜像启动一个容器,并将8080端口映射到主机。
三、常见实践
3.1 使用Multi-stage构建
Multi-stage构建允许我们在一个 Dockerfile
中使用多个 FROM
命令,从而简化镜像并减少最终镜像的体积:
dockerfile复制
# 第一阶段:构建应用
FROM maven:3.8-openjdk-11 as builder
WORKDIR /build
COPY . .
RUN mvn clean package
# 第二阶段:创建运行时镜像
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /build/target/my-java-app.jar /app/my-java-app.jar
EXPOSE 8080
CMD ["java", "-jar", "/app/my-java-app.jar"]
3.2 环境变量配置
在容器化应用中,使用环境变量进行配置是一种推荐做法。可以在 Dockerfile
中或在 docker run
命令中设置:
dockerfile复制
ENV APP_ENV=production
运行时覆盖:
bash复制
docker run -e APP_ENV=staging -d -p 8080:8080 my-java-app
3.3 日志管理
为了有效管理日志,建议将Docker容器的日志输出到stdout和stderr,以便使用Docker自带的日志驱动进行管理。
四、最佳实践
4.1 优化镜像体积
使用更小的基础镜像,比如
alpine
。清理不必要的构建依赖。
使用
.dockerignore
文件忽略不需要添加到镜像中的文件。
4.2 安全性考虑
使用非root用户运行应用。
定期更新基础镜像以获取安全补丁:
dockerfile复制
# 创建用户并使用
RUN addgroup --system appgroup && adduser --system appuser --ingroup appgroup
USER appuser
4.3 版本管理
为不同版本的应用打上不同标签:
my-java-app:1.0.0
。使用CI/CD工具自动化构建和推送镜像。
五、Docker在Java开发中的应用案例
5.1 部署Spring Boot应用
假设我们有一个简单的Spring Boot应用,项目结构如下:
复制
my-spring-boot-app
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── myapp
│ │ │ ├── controller
│ │ │ │ └── HelloController.java
│ │ │ └── MyAppApplication.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── static
│ │ └── index.html
│ └── test
│ └── java
│ └── com
│ └── example
│ └── myapp
│ └── MyAppApplicationTests.java
├── pom.xml
其中HelloController.java代码如下:
java复制
package com.example.myapp.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/")
public String hello() {
return "Hello, Docker with Spring Boot!";
}
}
MyAppApplication.java代码如下:
java复制
package com.example.myapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MyAppApplication {
public static void main(String[] args) {
SpringApplication.run(MyAppApplication.class, args);
}
}
1、创建 Dockerfile:在项目根目录下创建一个名为Dockerfile的文件,内容如下:
dockerfile复制
FROM openjdk:11
WORKDIR /app
COPY target/my-spring-boot-app-0.0.1-SNAPSHOT.jar /app/app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
2、构建项目:在项目根目录下执行mvn clean package
命令,生成可执行的 JAR 包。 3、构建镜像:在项目根目录下执行以下命令构建镜像:
bash复制
sudo docker build -t my-spring-boot-app .
4、运行容器:构建镜像成功后,就可以运行容器了:
bash复制
sudo docker run -d -p 8080:8080 my-spring-boot-app
5.2 多容器应用(以 Java Web 应用和 MySQL 为例)
1、添加依赖:在pom.xml文件中添加 MyBatis-Plus 和相关依赖:
xml复制
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>最新版本号</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
2、配置文件:在application.properties中添加数据库连接和 MyBatis-Plus 相关配置:
properties复制
spring.datasource.url=jdbc:mysql://mysql:3306/javadb?useSSL=false&characterEncoding=utf8
spring.datasource.username=javauser
spring.datasource.password=javapassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis-plus.mapper-locations=classpath:/mapper/*.xml
mybatis-plus.type-aliases-package=com.example.mywebapp.entity
3、代码实现:
User.java实体类:
java复制
package com.example.mywebapp.entity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("users")
public class User {
private Integer id;
private String name;
}
UserMapper.java接口:
java复制
package com.example.mywebapp.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mywebapp.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
IUserService.java接口:
java复制
package com.example.mywebapp.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mywebapp.entity.User;
public interface IUserService extends IService<User> {
}
UserServiceImpl.java实现类:
java复制
package com.example.mywebapp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mywebapp.entity.User;
import com.example.mywebapp.mapper.UserMapper;
import com.example.mywebapp.service.IUserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
}
UserController.java控制器:
java复制
package com.example.mywebapp.controller;
import com.example.mywebapp.entity.User;
import com.example.mywebapp.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user")
public User getUser(@RequestParam Integer id) {
return userService.getById(id);
}
}
MyBatisPlusConfig.java配置类(可选,用于自定义 MyBatis-Plus 配置):
java复制
package com.example.mywebapp.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.example.mywebapp.mapper")
public class MyBatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor;
}
}
4、创建 Dockerfile:在项目根目录下创建一个名为Dockerfile的文件,内容如下:
dockerfile复制
FROM tomcat:9.0
WORKDIR /usr/local/tomcat/webapps
COPY target/my-java-web-app.war ROOT.war
EXPOSE 8080
CMD ["catalina.sh", "run"]
5、构建项目:在项目根目录下执行mvn clean package
命令,生成可执行的 WAR 包。 6、构建镜像:在项目根目录下执行以下命令构建镜像:
bash复制
sudo docker build -t my-java-web-app .
7、运行容器:构建镜像成功后,就可以运行容器了:
bash复制
sudo docker run -d -p 8081:8080 --link my-mysql:mysql my-java-web-app
参数解释:
--link my-mysql:mysql
:将 Java Web 应用容器与 MySQL 容器建立链接,my-mysql
是 MySQL 容器的名称,mysql
是链接别名,方便在 Java Web 应用中通过mysql
来访问 MySQL 容器。-p 8081:8080
:将容器内部的 Tomcat 端口 8080 映射到主机的 8081 端口。
通过浏览器访问 http://localhost:8081/user?id=1
,就可以看到根据数据库查询结果展示的用户信息页面,这两个容器之间通过网络进行通信,协同工作