一文读懂:Docker从入门到进阶(超详细实践应用、零踩坑)

快速入门

简介

Docker是一个快速构建、运行、管理应用的工具。

传统的企业项目部署需要手动通过命令行安装环境和依赖,安装步骤复杂且常常会出现版本不兼容等问题。

借助Docker,我们只需要执行docker run命令即可一键让项目及其依赖在服务器成功运行起来。

由于项目通常在Linux系统部署,正式学习Docker前可以通过Vmware虚拟机安装CentOS系统。

Docker官网:https://www.docker.com/

安装

  1. 配置Docker的yum仓库:

    yum install -y yum-utils
    yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    
  2. 安装Docker:

    yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
    
  3. 启动和校验:

    # 启动Docker
    systemctl start docker
    
    # 停止Docker
    systemctl stop docker
    
    # 重启
    systemctl restart docker
    
    # 设置开机自启
    systemctl enable docker
    
    # 执行docker ps命令,如果不报错,说明安装启动成功
    docker ps
    

配置镜像加速

推荐使用阿里云的镜像加速服务。

  1. 找到产品->容器->容器镜像服务ACR。

    image-20240210182916494
  2. 找到镜像加速器并按照文档配置即可:

    image-20240210185642768

部署MySQL

用Docker部署MYSQL只需要执行如下命令即可:

image-20240210190027726
docker run -d \
	--name mysql \
	-p 3306:3306 \
	-e TZ=Asia/Shanghai \
	-e MYSQL_ROOT_PASSWORD=123 \
	mysql

当我们执行这个命令时,Docker会自动搜索并下载镜像(Image)。镜像不仅包含应用本身,还包含应用所需的环境、配置、函数库。

Docker会在运行镜像时创建一个隔离环境,称为容器(Container)。Docker官方维护了一个公共镜像Docker Hub用于存储和管理镜像。

下面详细介绍这条命令:

  • docker run:创建并运行一个容器,-d是让容器在后台运行。
  • –name mysql:给容器命名,必须唯一。
  • -p 3306:3306:端口映射,容器有自己的隔离网络系统,通过-p [宿主机端口]:[容器端口]可以进行端口映射。
  • -e:设置环境变量,-e KEY=VALUE。根据镜像的文档说明设置。
  • mysql:镜像名称,完整写法:[repository]:[tag],即[镜像名]:[版本]。默认是latest最新版本。

Docker基础

常见命令

image-20240211162755685

我们可以从镜像仓库拉取镜像或向镜像仓库推送镜像,常用命令:

  • docker push:将镜像推送到镜像仓库

  • docker pull:从镜像仓库拉取镜像到本地仓库

  • docker images:查看本地镜像

  • docker rmi:删除本地镜像

除了在镜像仓库获取镜像,也可以在本地编写dockerfile构建自己的镜像:

  • docker build:根据编写的dockerfile构建镜像

为了方便镜像传输,可以将镜像打包成压缩文件,常用命令:

  • docker save:将镜像打包成压缩文件保存在本地
  • docker load:将压缩文件加载到docker本地镜像仓库

有了镜像,可以通过如下命令创建容器并启动镜像:

  • docker run:创建并运行容器(如本地没有镜像会自动拉取)

对容器进行管理的常用命令:

  • docker stop:停止容器进程
  • docker start:启动容器进程
  • docker ps:查看运行中的容器
  • docker rm:删除容器
  • docker logs:查看容器运行日志
  • docker exec:进入容器内部执行命令

案例-部署Nginx

掌握了Docker的常见命令,现在来完成一个简单的案例,创建并运行Nginx容器。

  1. 首先,在Docker Hub搜索Nginx镜像,查看镜像名称。

    image-20240211163131603
  2. 通过docker pull nginx拉取镜像到本地,然后使用docker images查看本地镜像:

    image-20240211163301289
  3. 通过docker run -d --name nginx -p 80:80 nginx命令创建并运行容器,然后使用docker ps查看运行中的容器:

    image-20240211163632620
  4. 通过docker stop nginx停止容器,然后通过docker ps -a查看所有容器:

    image-20240211163920272
  5. 通过docker start nginx再次启动容器:

    image-20240211164005758
  6. 通过docker logs -f nginx查看日志,-f指follow持续输出日志(无法访问请关闭centos防火墙):

    image-20240211164443572
  7. 通过docker exec -it nginx bash命令进入容器并使用bash进行交互,-it指可交互终端。

    image-20240211164656153

命令别名

前面我们通过docker ps可以查看容器运行状态,但是输出的信息比较多。ps命令可以通过–format参数自定义输出格式:

docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"
image-20240211165126529

但是这个命令太复杂,我们可以借助Linux的别名来简化这个操作。通过vim ~/.bashrc命令编辑加入下面的指令:

alias dps='docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}\t{{.Names}}"'
image-20240211173337115

然后执行source ~/.bashrc,测试dps命令:

image-20240211173418654

数据卷挂载

我们以一个需求为例:

  1. 创建nginx容器,修改nginx容器内的html目录下的index.html文件。
  2. 将静态资源部署到nginx的html目录。

在Docker Hub查看nginx镜像官方文档,发现/usr/share/nginx/html为静态资源目录:

image-20240211173808064

通过docker exec -it nginx bash进入容器内部控制台,查看静态资源目录:

image-20240211173943054

通过vi index.html修改静态资源,发现不存在vi指令。原因是docker镜像包含的是服务运行所必须的依赖,而vi是非必须的。

image-20240211174324089

为了解决这个问题,我们可以使用数据卷:数据卷(volume)是一个虚拟目录,是容器内目录宿主机目录之间映射的桥梁。

我们创建数据卷,会在宿主机系统的/var/lib/docker/volumes/目录下创建相应的文件夹。容器和宿主机文件系统就可以实现双向绑定。

image-20240211174533872

如何创建数据卷呢?Docker为我们提供了相应的命令:

命令说明
docker volume create创建数据卷
docker volume ls查看所有数据卷
docker volume rm删除指定数据卷
docker volume inspect查看某个数据卷详情
docker volume prune清除数据卷

在执行docker run命令时,使用 -v 数据卷:容器内目录 可以完成数据卷挂载。如果挂载的数据卷不存在会自动创建数据卷。

执行docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx命令,挂载数据卷且创建并运行容器。

然后通过docker volume ls和docker volume inspect查看数据卷,容器内的html文件夹会映射到/var/lib/docker/volumes/html/_data文件夹。

image-20240211180901012

我们只需要修改/var/lib/docker/volumes/html/_data下的index.html即可:

image-20240211181106381

本地目录挂载

通过docker inspect可以查看容器详情,其中的Mounts代表挂载的数据卷,查看mysql容器:

image-20240211181530861

我们创建mysql容器时虽然没有创建和指定数据卷,但它还是挂载到了一个数据卷。这个数据卷由容器自行创建,称为匿名卷。

匿名卷映射了容器的/var/lib/mysql目录,这个目录存储了mysql的数据。匿名卷目录名非常长,不方便数据访问,最好在启动mysql容器时指定数据卷。

除了之前的数据卷挂载,我们也可以挂载到宿主机的本地目录:docker run -v 本地目录:容器内目录 可以完成本地目录挂载。

对于mysql,除了数据目录,还需要挂载配置文件、初始化脚本目录,这些目录可以查询Docker Hub的官方文档:

image-20240211182323741 image-20240211182350714

我们可以执行如下挂载:

  • /root/mysql/data -> /var/lib/mysql
  • /root/mysql/init -> /docker-entrypoint-initdb.d
  • /root/mysql/conf -> /etc/mysql/conf.d
docker run -d \
	--name mysql \
	-p 3306:3306 \
	-e TZ=Asia/Shanghai \
	-e MYSQL_ROOT_PASSWORD=123 \
	-v /root/mysql/data:/var/lib/mysql \
	-v /root/mysql/init:/docker-entrypoint-initdb.d \
	-v /root/mysql/conf:/etc/mysql/conf.d \
	mysql

DockerFile语法

DockerFile是一个文本文件,包含一个个指令说明执行什么操作来构建镜像。常见指令:

指令说明示例
FROM指定基础镜像FROM centos:6
ENV设置环境变量,可在后面指令使用ENV key:value
COPY拷贝本地文件到镜像的指定目录COPY ./jre11.tar.gz /tmp
RUN执行Linux的shell命令,一般是安装过程的命令RUN tar -zxvf /tmp/jre11.tar.gz && EXPORTS path=/tmp/jre11:$path
EXPOSE指定容器运行时监听的端口,是给镜像使用者看的EXPOSE 8080
ENTRYPOINT镜像中应用的启动命令,容器运行时调用ENTRYPOINT java -jar xx.jar

例:

# 指定基础镜像
FROM ubuntu:16.04
# 配置环境变量,JDK的安装目录、容器内时区
ENV JAVA_DIR=/usr/local
# 拷贝jdk和java项目的包
COPY ./jdk8.tar.gz $JAVA_DIR/
COPY ./docker-demo.jar /tmp/app.jar
# 安装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
# 入口,java项目的启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]

也可以直接基于JDK为基础镜像,省略一些步骤:

# 基础镜像
FROM openjdk:11.0-jre-buster
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]

自定义镜像

编写完DockerFile后可以通过 docker build -t [repository]:[tag] . 命令构建镜像。

  • -t:给镜像起名,不指定tag时默认为latest。
  • .:指定DockerFile所在目录,如果在当前目录就使用"."。

容器网络互联

每个容器都有自己的隔离网络。默认情况下,所有容器都是以bridge方式连接到Docker的一个虚拟网桥上。

Docker的默认网桥是docker0:172.17.0.1/16,如图所示:

image-20240211185512385

默认情况下,不同容器是可以相互连通的。但是容器的ip地址是动态的,每次重启可能会发生变化。

我们可以自定义网络,加入自定义网络的容器可以通过容器名互相访问,Docker的网络操作命令如下:

命令说明
docker network create创建一个网络
docker network ls查看所有网络
docker network rm删除指定网络
docker network prune清除未使用的网络
docker network connet使指定容器加入某网络
docker network disconnect使指定容器离开某网络
docker network inspect查看网络详细信息
  1. 通过docker network create创建网络并通过docker network ls查看网络:

    image-20240211190048727
  2. 通过ip addr指令查看发现多了一个虚拟网桥:

    image-20240211190142941
  3. 通过docker network connect simplicity mysql将mysql容器加入simplicity网络,然后通过docker inspect mysql查看网络信息:

    image-20240211190328439

此时,同网络中的其它容器可以通过 ping mysql 来访问这个容器。

除了这种方式,还可以在创建容器时加入 –network simplicity 使容器加入指定网络。

项目部署

部署Java应用

  1. 配置数据库信息。实际项目开发中的数据库连接参数通常用$来引用其它配置文件的变量,根据运行环境不同选择不同的数据库配置信息:

    image-20240211191659540

    例如,在本地(local)使用测试数据库,而在服务器(dev)正式部署使用mysql容器名:

    image-20240211191801878
  2. 通过Maven的package命令打包:

    image-20240211192238262
  3. 编写DockerFile:

    # 基础镜像
    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 service.jar /app.jar
    # 入口
    ENTRYPOINT ["java", "-jar", "/app.jar"]
    
  4. 将jar包和DockerFile放到同一个目录下,然后使用docker build -t “mall” .构建镜像:

    image-20240211192840599
  5. 通过docker run -d --name mall -p 8080:8080 --network simplicity mall创建并运行容器并通过docker logs -f mall查看日志:

    image-20240211193029061
  6. 此时,后端项目在Docker部署成功。我们可以将DockerFile和jar文件打包,其它人就可以构建镜像并运行容器。

部署前端

部署完毕后端,我们再来部署前端。通常使用nginx作为前端服务,我们需要部署静态资源目录html和conf配置文件。

对于nginx的conf,我们常在其中配置静态资源的目录、端口和代理。如:

worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/json;

    sendfile        on;
    
    keepalive_timeout  65;

    server {
        listen       18080;
        # 指定前端项目所在的位置
        location / {
            root /usr/share/nginx/html/mall-portal;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        location /api {
            rewrite /api/(.*)  /$1 break;
            proxy_pass http://mall:8080;
        }
    }
    server {
        listen       18081;
        # 指定前端项目所在的位置
        location / {
            root /usr/share/nginx/html/mall-admin;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        location /api {
            rewrite /api/(.*)  /$1 break;
            proxy_pass http://mall:8080;
        }
    }
}

上面的配置说明了用户端和管理端项目的端口、目录。此外,还通过代理转发了api接口到后端地址,解决了跨域的问题。

通过查询Docker Hub的官方文档,我们知道了nginx配置文件挂载方式:

image-20240211193753397

下面,开始通过Docker部署前端项目:

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 simplicity \
	nginx
image-20240211194218249

DockerCompose

尽管通过DockerFile直接Build镜像并创建容器运行已经很方便,但是对于Java项目我们需要分别运行Mysql、后端、前端的Docker容器,还是很繁琐。

DockerCompose为我们解决了这个问题,它通过一个单独的docker-compose.yml模板文件定义一组关联的容器,帮助我们实现多个关联容器的快速部署。

DockerCompose的简易模板:

image-20240211200253526

对于前面的项目部署,我们可以编写docker-compose.yml如下所示:

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:
      - mall-net
  mall:
    build: 
      context: .
      dockerfile: Dockerfile
    container_name: mall
    ports:
      - "8080:8080"
    networks:
      - mall-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:
      - mall
    networks:
      - mall-net
networks:
  mall-net:
    name: mall

可以看出来,compose只是整合了我们docker run中的参数。其中,depends_on指明了创建顺序。

我们只需要将相关的文件和Dockerfile和docker-compose.yml放到同一目录下,然后使用如下命令一键部署:

# 创建并启动所有容器(-f 指定composer文件位置,默认当前目录。-p 指定项目名。)
docker compose up -d
# 一键停止并移除所有容器、网络
docker compose down
# 查看容器进程状态
docker compose ps

以上利用composer实现了一键部署。DockerComposer的功能远不止于此,它可以借助DockerSwarm实现项目集群部署、多实例应用和负载均衡等。

在实际的项目开发中,程序员只需要编写好Dockerfile文件,会由专业的运维人员负责编写Composer实现集群和负载均衡的部署。

更进一步,在有些大企业中,程序员将后端代码push到仓库中后,会触发运维人员编写的自动化脚本对项目进行编译和部署。

### 回答1: 《Docker入门实践第三版pdf》是一本非常适合初学者的书籍,通过系统全面的介绍和实践指导,让读者能够快速了解和掌握Docker技术。 本书首先介绍了Docker的基础概念和原理,包括Docker镜像、Docker容器Dockerfile等。通过阅读这些内容,读者可以了解Docker在开发和运维中的优势和应用场景。 随后,本书详细讲解了Docker的安装和使用,包括Docker的常用命令、Docker Compose的使用、Docker Swarm和Kubernetes等容器编排工具的介绍。在实践方面,本书提供了许多具体的示例和案例,包括使用Docker进行Web开发、Java开发、Python开发、数据处理等多个方面的应用实践。 此外,本书还介绍了Docker与云计算、DevOps等技术的结合,详细讲述了Docker如何在现代化开发中发挥作用。 总的来说,本书非常适合想要了解和入门Docker技术的读者,内容详实、易懂、实用性强。无论是开发人员还是运维人员,都可以通过本书快速掌握Docker的基础知识和实践技能。 ### 回答2: 《Docker入门实践第三版》是一本介绍Docker技术的实用指南。它包括了Docker的基本概念、安装和使用方法、构建Docker镜像以及如何使用Docker容器进行开发和部署的详细内容。该书还介绍了Docker的网络和存储、Docker Compose以及Swarm等高级技术,帮助读者深入了解和掌握Docker的完整技术体系。 该书的第一章介绍了Docker的基础概念和优势,包括Docker的发展历程、Docker与虚拟机的比较、Docker的架构和组件等内容。第二章介绍了Docker的安装和配置方法,包括在不同操作系统上的安装方式,以及对Docker引擎的配置和优化。第三章介绍了Docker的基本使用方法,包括如何创建、运行、停止和删除Docker容器,以及如何使用Docker镜像和Dockerfile。 该书的后续章节介绍了如何使用Docker Compose进行多容器应用的部署,如何使用Docker Swarm进行分布式应用的部署和管理,以及如何使用Docker的网络和存储功能进行应用开发和调试。此外,书中还介绍了容器的安全性和性能优化等方面的内容,帮助读者深入理解和掌握Docker技术的细节和高级功能。 总的来说,《Docker入门实践第三版》是一本非常实用的Docker技术指南,适合初学者和有一定Docker经验的开发者阅读。该书内容详细、实用性强,可以帮助读者快速上手并深入掌握Docker应用方法和技术细节。 ### 回答3: Docker入门实践第三版pdf这本书主要介绍了Docker容器技术的基本原理和实践应用Docker容器技术是一种轻量级的虚拟化技术。本书首先介绍了Docker的基础知识,比如Docker镜像、Docker容器Docker仓库等。接着详细讲解了Docker的安装和配置,包括Linux和Windows平台的安装和配置步骤。 然后本书通过实际案例演示了Docker容器的使用,比如如何构建一个基于Docker的Web应用和数据库应用。此外还介绍了Docker Swarm和Kubernetes等容器编排工具的使用方法。 最后本书讲解了Docker的高级特性,比如Dockerfile、Docker Compose和Docker网络等。通过本书的介绍,读者可以了解到Docker容器技术的基本概念和实践,使读者能够快速上手Docker容器技术,并应用到实际项目中,提高工作效率。 总之,本书以简明易读、通俗易懂的方式,全面介绍了Docker容器技术的基本概念、实践方法和应用实例,是学习和掌握Docker容器技术的一本好书。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值