docker 学习笔记 - 快速上手

1、下载和安装

官网:https://docs.docker.com/get-started/get-docker/

# centos9 安装docker
# 配置 Linux 系统的 IP 转发功能
cat >> /etc/sysctl.conf <<-EOF
net.ipv4.ip_forward=1
EOF
#  重新加载 sysctl.conf
sysctl -p

# 通过yum包管理器安装三个软件包
yum install -y yum-utils device-mapper-persistent-data lvm2
# 添加阿里云 Docker 镜像仓库地址
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 更新 yum 缓存
yum makecache fast
# 安装 Docker 引擎
yum -y install docker-ce
# 启动 Docker 服务
service docker start
# 查看 Docker 版本信息
docker version
# 开机自启
sudo systemctl enable docker

配置国内镜像源(2025/4/10)

cat >> /etc/docker/daemon.json <<-EOF
{
  "registry-mirrors": [
    "https://docker.1ms.run",
    "https://docker.xuanyuan.me"
  ]
}
EOF
systemctl daemon-reload
systemctl restart docker

基本概念

1、镜像(Image)
    Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。
    镜像和容器 的关系,就像是面向对象程序设计中的类和实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

2、容器(Container)
    容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
按照 Docker 最佳实践的要求,容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。

3、仓库(Repository)
    镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样的服务。一个Docker Registry中可以包含多个仓库;每个仓库可以包含多个标签;每个标签对应一个镜像。
    通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

常用指令合集

配置非主用户也可以使用docker命令

# 查看是否有 docker 用户组
# 通常 Docker 安装后会自动创建一个名为 docker 的用户组。可以用下面命令查看:
cat /etc/group | grep docker

# 如果没有,可以手动创建
sudo groupadd docker
# 把 非 root 用户加入到 docker 组,-aG 表示 追加到组,而不是覆盖用户原有的组。
sudo usermod -aG docker huy(username)

# 使组更改立即生效
newgrp docker

修改容器内配置文件

在启动容器后想要修改容器内的配置文件,基本都是将配置文件先复制出容器,因为在里面是没有配置vi的。

docker cp <源路径> <目标路径>

# 从容器复制到主机:
docker cp <容器ID或名称>:<容器内路径> <主机路径>

# 从主机复制到容器:
docker cp <主机路径> <容器ID或名称>:<容器内路径>

# 修改配置以后重启指令
docker restart <容器ID或容器名称>

部分经常会变动的文件可以使用挂载

镜像

拉取镜像docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

  • 示例:docker pull [docker.1ms.run/library/]tomcat:9
  • []表示可选项,前面配置了国内镜像可以不用写

查看所有镜像docker images

    docker images 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。

查看镜像细节docker inspect tomcat:9

移除镜像docker rmi tomcat:9

运行docker run tomcat:9(容器命令里详解)

查看镜像、容器、数据卷所占用的空间docker system df

tomcat:9 这里是 REPOSITORY,也可以是 IMAGE ID,(docker images 可见)

容器命令

运行容器指令docker run -d -p 8000:8080 --name tomcat9 tomcat:9
-p 8000:8080:将容器的 8080 端口映射到宿主机的 8000 端口

-d 表示以 detached 模式(后台模式)运行容器

--name 为启动容器起别名

还可以添加如

-rm 表示容器退出后随之将其删除

-v 挂载

-e 参数用于设置环境变量(格式 -e VAR1=value1 -e VAR2=value2 ...)

--env-file (后接需要读取的文件 和 启动的容器)

--network (后接网络名称,适用于容器之间网络互通,docker network create -d bridge my-net 创建网络)

此时访问 ip地址:8000 即可看到 tomcat 404 的界面了,创建 index.html 使用下示例指令即可修改启动界面

mkdir ROOT
echo '<h1>Hello, Docker!</h1>' > /usr/local/tomcat/webapps/ROOT/index.html

docker run 在本地没有镜像的时候会远程先拉去一个镜像再启动镜像

支持启动时资源限定
--memory 500m 限定容器的内存资源 为 500MB
--network-bandwidth 1G 限定容器的网络带宽


查看启动容器docker ps
-a :列出所有容器(包括正在运行的和已停止的容器),不加默认显示正在运行的容器

暂停容器docker pause <容器名称或ID>

恢复容器的运行状态: docker unpause <容器名称或ID>

停止容器: docker stop <容器名称或ID>

重新启动容器:docker start <容器名称或ID>

进入容器: docker exec -it tomcat9 /bin/bash

-i:交互式模式。

-t:分配一个伪终端。

-/bin/bash:指定在容器中启动一个 Bash shell。

挂载和卷

在容器中管理数据(数据持久化)主要有两种方式:

  • 数据卷(Volumes)
  • 挂载主机目录 (Bind mounts)

数据卷 是一个可供一个或多个容器使用的特殊目录,被设计用来持久化数据的,它绕过 UnionFS,可以提供很多有用的特性:

  • 数据卷 可以在容器之间共享和重用
  • 对 数据卷 的修改会立马生效
  • 对 数据卷 的更新,不会影响镜像
  • 数据卷 默认会一直存在,即使容器被删除

创建一个数据卷:docker volume create my-vol

查看所有数据卷:docker volume ls

查看指定数据卷的信息:docker volume inspect my-vol

删除卷:docker volume rm my-vol

删除无主卷:docker volume prune

示例

mkdir /home/init.d
cat>/home/init.d/db.sql<<-'EOF'
USE Test;
CREATE TABLE IF NOT EXISTS User(
    ID INT AUTO_INCREMENT PRIMARY KEY,
    Name VARCHAR(50) NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
EOF

docker run 
--name mysql8
-v /home/init.d:/docker-entrypoint-initdb.d
-v my-vol:/var/lib/mysql 
-e MYSQL_DATABASE=Test 
-e MYSQL_ROOT_PASSWORD=root 
-d mysql:8.0.22

docker-entrypoint-initdb.d 是 Docker 容器中一个特殊的目录,主要用于在容器启动时自动执行初始化脚本。

定制镜像

    镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入一个脚本,用这个脚本来构建、定制镜像,那么之前提及的无法重复的问题、镜像构建透明性的问题、体积的问题就都会解决。这个脚本就是 Dockerfile。
    Dockerfile 是一个文本文件,其内包含了一条条的 指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。
创建一个 dockerfile

FROM stretch

RUN set -x; buildDeps='gcc libc6-dev make wget' \
    && apt-get update \
    && apt-get install -y $buildDeps \
    && wget -O redis.tar.gz "http://download.redis.io/releases/redis-5.0.3.tar.gz" \
    && mkdir -p /usr/src/redis \
    && tar -xzf redis.tar.gz -C /usr/src/redis --strip-components=1 \
    && make -C /usr/src/redis \
    && make -C /usr/src/redis install \
    && rm -rf /var/lib/apt/lists/* \
    && rm redis.tar.gz \
    && rm -r /usr/src/redis \
    && apt-get purge -y --auto-remove $buildDeps

FROM 就是指定 基础镜像
Dockerfile 中 FROM 是必备的指令,并且必须是第一条指令。
以 scratch 为基础镜像的话,意味着不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

RUN 指令是用来执行命令行命令的。由于命令行的强大能力,RUN 指令在定制镜像时是最常用的指令之一。其格式有两种:

  • shell 格式:RUN <命令>,就像直接在命令行中输入的命令一样。刚才写的 Dockerfile 中的 RUN 指令就是这种格式。
  • exec 格式:RUN ["可执行文件", "参数1", "参数2"],这更像是函数调用中的格式。

常用指令:

  • FROM:指定基础镜像。所有的 Dockerfile 必须以 FROM 开头,用来选择一个官方提供的镜像或者自定义的基础镜像。
  • RUN:执行命令并创建新的镜像层。这些命令会在构建过程中被执行,并且会被记录为镜像的一部分。
  • LABEL:为镜像添加元数据。例如,可以添加作者信息或版本号。
  • ENV:设置环境变量。这些变量可以在后续的 RUN 指令中使用,也可以在容器运行时被访问。
  • ADD 和 COPY:将文件从主机复制到镜像中。ADD 提供了额外的功能,比如支持远程 URL 和自动解压 tar 文件。
  • VOLUME:创建挂载点,允许外部访问容器内的特定目录。
  • USER:切换执行命令的用户。这对于提高安全性非常有用。
  • WORKDIR:设置工作目录。类似于 Linux 的 cd 命令,它会改变当前的工作目录。
  • ENTRYPOINT:配置容器启动时运行的命令。不同于 CMD,ENTRYPOINT 不会被后面的命令覆盖。
  • CMD:提供默认的执行参数,当没有指定其他参数时,该命令会被执行。与 ENTRYPOINT 一起使用时,CMD 可以作为 ENTRYPOINT 的默认参数。
  • EXPOSE:告知 Docker 容器在运行时监听的端口。这只是一个声明,不会自动打开端口。
# dockerfile
# 使用 OpenJDK 官方镜像作为基础镜像
FROM openjdk:17-jdk-slim

# 设置工作目录
WORKDIR /app

# 将本地的 jar 文件复制到容器的 /app 目录下
COPY target/your-app.jar /app/your-app.jar

# 暴露应用的端口,假设是 8080
EXPOSE 8080

# 启动 Spring Boot 应用
ENTRYPOINT ["java", "-jar", "your-app.jar"]
# docker-compose.yml
version: '3.8'

services:
  springboot-app:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - mysql
      - redis
    environment:
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/your_database
      - SPRING_DATASOURCE_USERNAME=root
      - SPRING_DATASOURCE_PASSWORD=your_password
      - SPRING_REDIS_HOST=redis
    networks:
      - app-network

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: your_password
      MYSQL_DATABASE: your_database
    ports:
      - "3306:3306"
    networks:
      - app-network

  redis:
    image: redis:6.2
    ports:
      - "6379:6379"
    networks:
      - app-network

networks:
  app-network:
    driver: bridge

docker-compose 是一个用于定义和管理多个 Docker 容器的工具,它通过一个 docker-compose.yml 配置文件来描述应用中的各个服务、网络、卷等,从而简化了多容器的管理和部署。它的优势在于可以让你用一个命令来启动、停止、查看日志等操作所有的容器,方便处理复杂的应用部署。

  • version:指定 Docker Compose 文件的版本,3.8 是一个较新的稳定版本。
  • services:定义了多个服务,每个服务代表一个容器。每个服务都可以配置如下:
    • build:指定当前目录下的 Dockerfile 用于构建镜像(可选)。如果镜像已经构建好,可以使用 image。
    • image:指定要使用的 Docker 镜像。如果没有指定 build,可以直接指定镜像名。
    • ports:映射容器的端口到宿主机的端口。
    • environment:设置容器的环境变量,通常用于数据库连接配置等。
    • depends_on:指定服务的依赖关系,确保依赖的服务(如数据库)先启动。
    • networks:指定该服务所属的网络,用于容器间的通信。

networks:定义多个网络,容器可以根据需要连接到这些网络。这有助于确保服务之间的隔离性,或让多个服务共享网络。

网络

Docker 网络是 Docker 容器之间通信的基础。Docker 提供了多种网络类型,包括:

  • bridge 网络:这是默认的网络类型,它使用 Docker 的虚拟网桥来实现容器之间的通信。每个容器都有一个独立的 IP 地址,并且可以通过容器的名称或 ID 来访问。
  • host 网络:容器使用宿主机的网络栈,容器的网络配置与宿主机完全相同。这意味着容器可以直接访问宿主机的网络接口,并且可以直接使用宿主机的 IP 地址。
  • overlay 网络:这是一种分布式网络,用于在多个 Docker 守护进程之间实现容器之间的通信。它使用虚拟交换机来实现容器之间的通信。
  • macvlan 网络:这是一种基于 MAC 地址的网络,它允许容器使用宿主机的物理网络接口来实现容器之间的通信。
  • none 网络:容器没有网络连接,容器的网络配置与宿主机完全相同。这意味着容器无法访问宿主机的网络接口,并且无法使用宿主机的 IP 地址。

创建网络:docker network create my-net
查看网络:docker network ls
删除网络:docker network rm my-net
查看网络详情:docker network inspect my-net
连接容器到网络:docker network connect my-net container-name
断开容器与网络的连接:docker network disconnect my-net container-name
删除容器时自动断开与网络的连接:docker run --network my-net --rm container-name
查看容器的网络连接:docker network inspect container-name
查看容器的网络连接:docker network inspect container-name

参考:https://vuepress.mirror.docker-practice.com/#

posted @ 2025-04-14 22:10  虚拟式  阅读(18)  评论(0)    收藏  举报