docker

Docker

学神Docker

1
2
3
容器:docker、containerd、podman
k8s1.24版本舍弃docker容器了,安装镜像时不使用docker用containerd
但是创建镜像还是常用docker命令

docker概述

Docker 是容器的称呼,常见的容器除了 docker 外,还有containerd、podman、CRI-O等,开发写好的代码或者需要部署的服务,都打包到一个镜像里,然后基于docker 或者containerd或者podman运行镜像,就可以提供相应的服务了。

现在用containerd运行容器比较多

centos:基于Red Hat Enterprise Linux

rocky-linux

Ubuntu:基于Debian

Fedora:有Red Hat公司支持

openstack:私有云技术

麒麟:由中国国防科技大学、中软公司、联想公司、浪潮集团和民族恒星公司合作研制的商业闭源服务器操作系统

欧拉:华为的操作系统

服务器:

虚拟机:虚拟机技术通过虚拟化硬件资源(例如CPU、内存、存储等)来创建一个完整的虚拟计算机,其中包含独立的操作系统、应用程序和用户数据。每个虚拟机都像一个独立的物理计算机,可以运行不同的操作系统和应用程序。虚拟机的启动时间较慢,占用的系统资源相对较多。

容器:只有一个操作系统。容器可以共享宿主机的操作系统内核,并在容器中运行应用程序及其依赖项。容器启动时间较快,占用的系统资源相对较少

docker:创建镜像、运行容器

containerd:只能运行容器

podman:创建镜像、运行容器

CRI-O:只能运行容器

云原生:docker、k8s、Prometheus等

传统开发的代码如何跑起来

之前开发的代码编译成可执行文件给运维到服务器、虚拟机、云主机上运行。需要包含go、java、python等环境

GO开发

Go开发的代码:go build 编译->main.go->生成一个二进制文件 如: k8sdemo->chmod +x k8sdemo->./k8sdemo

到服务器、虚拟机、云主机上运行二进制文件

JAVA开发

Java开发:mvn编译打包之后,生成一个jar包,java -jar指定jar包运行

PYTHON开发

python hello.py

C#开发

NGINX

nginx安装:yum install nginx、源码、二进制

容器方式

自从有了你(容器):把这些都打包到镜像里,基于docker 运行镜像
这些指的是啥?代码编译之后可以运行的文件,如jar、二进制文件

docker的特点

优点:
1、高度可移植性:Docker 可以在任何支持 Docker 的平台上运行,而且容器可以在不同的环境中快速、简单地部署和移植。
2、轻量级和高效:Docker容器非常轻量级,启动和停止速度快,并且对系统资源的占用非常少。

3、隔离性好:Docker 使用Namespace 和cgroups 技术实现容器的隔离,每个容器都拥有自己的进程、网络、文件系统和其他资源,保证了容器之间的隔离性和安全性。

4、易于管理和扩展:Docker 提供了一系列的命令行工具和图形化界面,可以方便地管理和监控容器。同时,Docker 还支持容器编排工具,如Kubernetes,可以轻松地管理和扩展容器集群。

5、生态系统丰富:Docker 拥有庞大的社区和生态系统,提供了丰富的容器镜像和插件,可以方便地构建、部署和运行应用程序。

docker基本概念

镜像

镜像(Image):一个可运行的二进制文件,包含了运行应用程序所依赖项和配置信息。可以通过编写 Dockerfile 文件来创建镜像。

镜像不仅包含应用本身,还包含应用运行所需要的环境、配置、系统函数库。Docker会在运行镜像时创建一个隔离环境,称为容器(container)

仓库查看镜像时会有相关的详细说明

镜像有层的概念,添加安装包、依赖、配置等,每一次操作都形成新的一层。

分层的好处包括:有的镜像的底层镜像是一样的,前面其它镜像下载过,当前镜像就不用下载了。

基础镜像包含应用依赖的系统函数库、环境、配置、文件等。

入口:镜像运行入口,一般是程序启动的脚本和参数

基础镜像->层->入口

容器

容器(Container):一个运行中的镜像实例,包含了应用程序和其依赖项。可以使用 Docker CLI或 Docker Compose(只负责跑服务,不如K8S用的多) 来创建和管理容器。

仓库

仓库(Registry):一个存储和分发镜像的地方。Docker Hub 是 Docker 官方提供的仓库,可以在其中找到许多常用的镜像,也可以在其中上传和分享自己的镜像。

Dockerhub(只适合下载不适合上传):Dockerhub是存放docker 镜像的一个官方网站,dockerhub上提供了很多常用的镜像供用户下载,如 ubuntu、centos、debian 等操作系统镜像。通过 dockerhub用户也可以存自己的docker镜像,但是需要需要注册一个账号,在网站上创建一个docker 仓库。

基于公开仓库提供的基本镜像,开发新的镜像

公共仓和私有仓

公司可以自己搭建镜像仓库,私服

网址

docker官网:www.docker.com

docker github网址:github.co/moby/moby

docker hub官网:registry.hub.docker.com

docker hub国内替代网站:hub-stage.docker.com/

答疑

1
2
docker打的包,为啥containerd能导入用?
containerd提供ctr命令解开镜像,只要是镜像其实是相通的

安装

准备linux环境

环境准备、静态ip、主机名、防火墙、时间同步

yum install lrzsz vim-enhanced -y

安装yum-utils工具

yum install -y yum-utils

配置docker的yum源

yum-config-manager -add-repo https://download.docker.com/linux/centos/docker-ce.repo

安装docker

yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

查看版本检查是否安装成功

docker -v

docker version

启动服务

systemctl start docker

systemctl stop docker

systemctl enable docker # 设置开启自启

systemctl status docker # 查看docker转态

镜像加速

阿里云->容器镜像服务免费加速

镜像加速:/etc/docker/daemon.json

systemctl restart docker

部署Mysql

1
2
3
4
5
6
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_ROOT_PASSWORD=123 \
mysql

用宿主机的IP和对应端口就可以连到mysql了

命令

docker search 镜像名 # 默认从官方镜像库查询

docker images # 镜像存放路径 /var/lib/imags 迁移镜像可以直接拷贝这个目录,不用每个镜像都打成压缩包

docker inspect 镜像

docker tag 镜像名:版本 新镜像名:新版本 # 会创建一个tag不同,id相同的镜像

docker run -d -p 80:80 nginx #镜像不存在会自动从docker hub下载

https://blog.csdn.net/fim77/article/details/143844100

1
2
3
4
5
6
7
8
9
10
11
12
13
镜像 镜像库 
容器

-v
不一定要把代码项目路径挂载上,像不需要代码修改的场景、代码打包成镜像等不需要挂载
开发时需要,将代码同步到开发环境
持久化数据时需要
挂载配置文件
docker run python3 xxx.py镜像内没有代码不行,而且这种在docker run时直接执行命令有-v时也不行,这种一定代表代码里有对应代码。通过-v这种方式可以进入容器后再执行-v里的代码
-v ..\test\:\workspace\ 代表把前者里的所有内容挂载进去

露姐案例:
docker run -it --rm --name 3D_detect --shm-size=32g --gpus all -v /home/lium/dynamic_target_visualisation/.vscode-server:/root/.vscode-server -v /home/lium/dynamic_target_visualisation/:/root/dynamic_target_visualisation/ changan-map.tencentcloudcr.com/train/3donenet:v20251119

镜像

下载镜像

命令:
docker pull docker.io/library/xxx:latest 注意是官方库可以省略的部分

dockerhub: hub.docker.com
dockhub的镜像站:docker.fxxk.dedyn.io

给docker配置镜像站:daemon.json

docker pull –platform=xxxx 一般linux上下载docker镜像会自动选择适合宿主机处理器架构的镜像

可以直接不下载直接使用docker run,创建运行容器时自动下载镜像

1
docker pull mysql # 不写版本号默认是最新版本

查看本地镜像

docker images

包含镜像名、版本、ID、创建时间、大小

删除镜像

docker rmi id/名字

构建镜像

dockerfile

https://docs.docker.com/reference/dockerfile

dockerfile 描述镜像是如何创建的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ARG 使用执行构建命令时的参数 Use build-time variables
FROM 指定基础镜像
ENV 设置环境变量,可在后面指令使用
WORKDIR 设置容器工作目录
COPY 拷贝本地文件或者目录到镜像的指定目录
RUN 执行Linux的shell命令,一般是安装过程的命令
CMD [] 一个dockerfile里只能有一个cmd
EXPOSE 指定容器运行时监听的端口,是给镜像使用者看的(创建容器时还是通过-p指定)
ENTRYPOINT 镜像中应用的启动命令,容器运行时调用。比cmd优先级更高,不容易被覆盖


RUN 构建时执行、安装、解压、删除等
CMD 运行时执行,为容器提供默认的执行命令,可以被 docker run后面的命令覆盖
ENTRYPOINT 运行时执行
1
2
3
4
5
6
7
8
9
10
11
12
ARG BASE_IMAGE 
FROM $BASE_IMAGE
WORKDIR /workspace

#设置环境变量
ENV CAFS_SDK_USE_PROVIDER_PROXY=true
ENV CAFS_SDK_PROVIDER_PROXY="{\"xxx":[\"xxx",\"xxx\"]}"

RUN rm -rf *
COPY src /workspace/
RUN ./install.sh && rm -rf /var/lib/apt/lists/*
EXPOSE 3030
1
2
3
4
5
通过ARG指令允许在构建时动态指定BASE_IMAGE 
设置CAFS_SDK_USE_PROVIDER_PROXY为true,启用代理
设置CAFS_SDK_PROVIDER_PROXY,配置
RUN执行命令
暴露3030端口供外部访问
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ARG BASE_IMAGE
FROM $BASE_IMAGE

# 设置环境变量
# 防止包安装时交互式提示 设置 Debian/Ubuntu 系统的环境变量
ENV DEBIAN_FRONTEND=noninteractive

WORKDIR /workspace

COPY install.sh requirements.txt .

RUN ./install.sh

RUN rm -rf install.sh requirements.txt
1
2
3
COPY src_tmp .
COPY . .是将当前目录下所有内容,复制到workspace,文件夹的话是包含文件夹名的
COPY src . 复制src里的内容到.
案例 部署java应用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 指定基础镜像
FRON 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/java
ENV PATH=$PATH:$JAVA_HOME/bin
# 入口,java项目的启动命令
ENTRYPOINT ["java","-jar", "/app.jar"]

下面这个基础镜像已经把系统、java、还有配置弄好了

1
2
3
4
5
6
# 基础镜像
FROM openjdk:11.0-jre-buster
# 拷贝jar包
COPY docker-demo.jar /app.jar
# 入口
ENTRYPOINT ["java", "-jar", "/app.jar"]
docker build命令

docker build -t paran/myapp:3.0 -f ./Dockerfile .

-t –tag: 用于为构建的镜像指定标签和名称,格式为 [仓库地址]/[用户名]/[镜像名]:[标签],不写仓库地址默认就是docker hub的地址,没有私服可以不用管。
-f –file:指定 Dockerfile 的路径和文件名。
. 代表构建上下文的路径,也就是告诉 Docker,将当前目录及其包含的所有文件和子目录作为构建镜像时可访问的范围。

1
2
3
4
5
docker build -t 镜像名字[:版本可不指定] . 

然后就可以使用自定义的镜像创建运行了

发布镜像到dockerhub
1
2
3
4
5
docker build -f $DOCKERFILE --build-arg BASE_IMAGE=$BASE_IMAGE  -t $TARGET_IMAGE .

. 它是 docker build命令的最后一个参数,指定了构建上下文的位置。
它告诉 Docker 引擎:从哪里获取构建所需的所有文件(即“构建上下文”)。
Dockerfile 中 COPY、ADD等指令的相对路径,都是相对于这个目录的。
1
2
3
4
5
6
[liuj@VM-16-2-tencentos static_dynamic_annotation]$ docker run -it changan-map.tencentcloudcr.com/train/static_dynamic_annotation:v2.2 /bin/bash

/bin/bash: /bin/bash: cannot execute binary file
原因:您主机的系统架构(例如x86_64/amd64)与Docker镜像的架构(例如arm64)不一致。您尝试在一个架构上运行为另一个架构编译的/bin/bash二进制文件,导致无法执行

uname -m
1
2
3
检查镜像架构(将[您的镜像名]替换为实际名称,如ubuntu:latest):

docker image inspect [您的镜像名] | grep -i architecture

打镜像为压缩包

实际工作中很少用这种方式,一般都是使用docker pull

docker save -o 文件名.tar.gz(可以不要.tar.gz) 镜像[:tag]

从压缩包中加载镜像

从压缩包中获取镜像:docker load -i 压缩包

发布镜像

1
2
3
4
5
# 镜像打个标签
docker tag 本地镜像名:tag namespace/仓库名


docker push namespace/仓库名

容器

创建容器和运行

docker run:用于创建运行一个新的容器。

它会先检查本地是否存在指定的镜像,如果不存在,则会从默认的镜像仓库(如 DockerHub)中拉取该镜像,然后基于该镜像创建容器,并为容器分配所需的资源,最后启动容器内的应用程序。

如果镜像已经存在,则直接使用本地镜像创建并启动容器

docker run -d -p 80:80 –name 容器名字 镜像名[:xxx]

-d 让容器在后台运行

–name 给容器起一个名字(要唯一)

-p 端口映射(为了使其它机器能够通过宿主机ip和端口连接到容器服务)

[:xxx] :tag不设置默认为最新镜像

client敲命令->Docker server(docker daemon)<=>docker hub

1
2
3
4
docker run --rm -v /home/xxx/.vscode-server:/root/.vscode-server \ 
-v $CODE_PATH:/workspace \
--name $container_name \
-it xxxx:$Tag /bin/bash
1
2
3
docker run时直接执行命令

nohup docker run --net=host -d -v /data01/zxx/config:/data/config --rm changan-map.tencentcloudcr.com/train/stdata_preprocess:v1.0.3 /bin/bash -c "python3 run_output.py --tasks $datname --run-type 2 --config /data/config/output.yaml" > ./output$i.log 2>&1
1
2
3
4
5
6
7
8
9
执行容器后,使vscode能直接连接容器

docker run --net=host \
-v /home/$(whoami)/.vscode-server:/root/.vscode-server \
-v /data01/zxx/config:/data/config \
--name test \
-it \
changan-map.tencentcloudcr.com/train/stdata_preprocess:v1.0.3 \
/bin/bash

设置容器环境变量 -e

1
2
3
4
5
-e参数  
docker run -e xxx=xxx -d -p... -v... 镜像

创建mongdb容器
创建mongodb网页端容器

-it参数

-it参数 可以让交互页面进入docker交互页面
docker run -it -rm alpine 轻量级linux系统 停止运行后删除,调试很有用

进入容器的交互界面

docker exec -it 容器 /bin/sh

docker exec -it rabbitmq bash

–restart参数

第一个命名在docker停止后会重启,第二个手动停止不会重启 生产环境
docker run -d –restart always nginx
docker run -d –restart unless-stopped nginx

案例

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

创建容器

docker create和run类似 但只创建

启动和暂停容器

用于启动已经创建但处于停止状态的容器。它不会创建新的容器,也不会检查或拉取镜像,而是直接启动之前已经创建好的处于停止状态的容器,使容器内的应用程序或进程继续运行。

docker start/stop 容器 会保留之前启动的参数

查看运行中的容器

1
2
3
4
docker ps 显示正在运营容器 (-a 显示包括非运行的容器)
--format "table ....."

可以显示:容器id 所属镜像 容器名字等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
docker ps
CONTAINERID IMAGE COMMAND CREATED STATUS PORTS NAMES

docker ps -a --format "{{.Names}}" | grep -q "^$container_name$"
{{.Names}}是一个 Go 模板占位符,它告诉 Docker 命令只输出容器的名称

-q参数表示“安静模式”。grep不会在屏幕上输出任何匹配到的内容,它只关心是否找到了匹配项。如果找到,grep会以退出码 0 结束;如果没找到,则以退出码 1结束。

^$container_name$是一个正则表达式模式:

^表示“行的开始”。

$container_name是一个 Shell 变量,它应该包含了您想查找的容器名称。

$表示“行的结束”

linux命令别名

docker ps -a –format “…..”

命令太长,可以使用linux别名,在~/.bashrc进行配置

查看容器的信息

docker inspect 容器 查看容器的信息

1
docker inspect <container_id_or_name> | grep -A 10 "NetworkMode"

在容器内部执行命令

docker exec -it 容器 ps -ef

docker exec -it rabbitmq bash 使用bash命令行交互操作

docker exec -it mysql mysql -uroot -p

-i 交互式环境 -t 伪终端

bash

sh

/bin/sh

/bin/bash

重命名容器名

docker rename 旧容器名 新容器名

删除容器

1
2
3
docker rm 容器名/ID  # 容器需停止

docker rm -f id 强制删除正在运行的容器需要f

数据卷

数据卷(volume)是一个虚拟目录,是容器内目录与宿主机目录之间映射的桥梁。方便我们操作容器内文件,或者方便迁移容器产生的数据

绑定挂载数据卷 -v

绑定挂载:宿主目录写成实际存在的目录、会覆盖容器目录内容。写绝对路径/或者./两种方式,不然会被识别成数据卷而不是真实目录

宿主机目录:这里它就是数据卷

1
docker run  -d -p 80:80 -v 宿主机目录:容器目录 镜像id或者名字  

映射文件和文件夹都行

1
2
3
4
5
挂载本地目录
-v 本地目录:容器内目录

挂载本地文件
-v 本地文件:容器内文件
1
2
3
4
5
6
7
不一定要把代码项目路径挂载上,像不需要代码修改的场景、代码打包成镜像等不需要挂载 
开发时需要,将代码同步到开发环境
持久化数据时需要
挂载配置文件

案例:
docker run -it --rm --name 3D_detect --shm-size=32g --gpus all -v /home/lium/dynamic_target_visualisation/.vscode-server:/root/.vscode-server -v /home/lium/dynamic_target_visualisation/:/root/dynamic_target_visualisation/ changan-map.tencentcloudcr.com/train/3donenet:v20251119

注意:容器与数据卷的挂载要在创建容器时配置,对于创建好的容器,是不能设置数据卷的

案例

mysql容器默认会自动创建一个数据卷(匿名卷)将容器内数据存储目录,通过命令挂载的方式绑定到宿主/var/lib/mysql上。

缺点:数据卷名字太长,重新创建mysql容器时数据没有迁移

做mysql配置文件、初始化脚本、数据目录挂载(mysql镜像有详细说明)

1
2
3
4
5
6
docker run -d \
--name mysql \
-p 3306:3306 \
-e TZ=Asia/Shanghai \
-e MYSQL_RO0T_PASSWORD=123 \
-v /root/mysql/data:/var/lib/mysql\-v /root/mysql/init:/docker-entrypoint-initdb.d \-v /root/mysql/conf:/etc/mysql/conf.d1mysql

命名挂载数据载

宿主目录(数据卷)不存在时(会自动创建),数据在目录/var/lib/docker/volumes/xxx/_data。存在时就在对应目录

1
docker run -d --name nginx -p 80:80 -v html:/usr/share/nginx/html nginx
1
2
3
4
5
6
7
8
9
docker volume create xxx 

docker run -d -p 80:80 -v 数据卷名字:容器目录 镜像id或者名字

docker volume inspect 数据卷名字 查看数据卷的详细信息,如显示挂载卷的真实位置

docker volume rm xxx

docker volume prune -a 删除所有没有容器使用的卷

查看已有的数据卷

1
docker volume list 

查看数据卷详细信息

docker volume inspect xxx

查看容器内linux系统信息

cat /etc/os-release 查看容器内linux系统信息,容器内的系统简洁有的工具不自带

容器日志

docker logs 容器

docker logs 容器 -f 动态显示日志

容器网络 容器子网

创建子网

1
docker network create 子网名 

显示所有网络

1
docker network list 显示所有docker网络

查看网络信息

1
docker network inspect	查看网络详细信息

删除网络

1
2
3
docker network rm xxx 删除网路 

docker network prune # 删除所有没有被使用的网络

网络模式

1
2
3
4
5
6
7
桥接模式(默认)
--network 子网名

host模式 直接使用宿主机网络和端口
--network host

none模式 没有网络
案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
docker network create network1

docker run -d \
--name my_mongodb\
-e MONGO_INITDB_ROOT_USERNAME=name\
-e MONGO_INITDB_ROOT_PASSWORD=pass\
-v /my/datadir:/data/db\
--network network1\
mongo

docker run -d \
--name my_mongodb_express\
-p 8081:8081\
-e ME_CONFIG_MONGODB_SERVER=my_mongodb\
-e ME_CONFIG_MONGODB_ADMINUSERNAME=name\
-e ME_CONFIG_MONGODB_ADMINUSERPASSWORD=pass\
--network network1\
mongo-express

连接到网络

1
2
3
docker network connect 网络名 容器名	让指定容器加入某个网络

docker network disconnect 网络名 容器名 让指定容器离开某个网络

案例

1
2
1
2
3
4
docker network connect mynet nginx
docker network connect mynet mysql

把nginx和mysql加入到同一个网络,然后进入nginx,ping mysql,发现可以ping通

docker compose

作用

作用:允许用户通过一个 YAML 格式的配置文件来配置多个相关联的容器,使得复杂的多容器应用的部署、启动、停止和管理变得更加简单和高效。

快捷创建多个容器,方便管理的容器编排技术,使用yml文件管理多个容器。

yml文件定义各个容器如何创建和如何协同工作的

配置容器启动顺序

yml文件文件里可以定义容器启动顺序dependson

启动容器

1
2
3
4
5
6
docker compose up -d(同dockercompse文件目录下) 启动yml文件里定义的容器

标准的名字是docker-compose.yaml,如果是其它名字需要加-f
docker compose up -d -f test.yaml(其它名字) 启动yml文件里定义的容器

docker compose start (同dockercompse文件目录下) 启动用dockercompose文件创建但已停止的容器

停止容器

1
2
3
docker compose down(同dockercompse文件目录下) 停止并删除容器

docker compose stop (同dockercompse文件目录下) 停止容器

网络

docker compose文件默认所有容器自动加入同一个子网

1
2
3
4
5
6
docker compose文件默认所有容器一个子网yml文件
文件里可以定义容器启动顺序dependson

docker compose up -d 启动yml文件里定义的容器

docker compose down

案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
version: '3.9'
services:
mysql:
image: mysql:8.0.32
container_name: mysql
environment:
TZ: Asia/Shanghai
MYSQL_ROOT_PASSWORD: 123456
ports:
- "3306:3306"
volumes:
- ./mysql/sql:/docker-entrypoint-initdb.d
networks:
- my-network

redis:
image: redis:6.2
container_name: redis
ports:
- 6379:6379
volumes:
- ./redis/redis.conf:/usr/local/etc/redis/redis.conf
networks:
- my-network

networks:
my-network:
driver: bridge