1、docker常用操作

1、启动docker

参考:https://zhuanlan.zhihu.com/p/544310970
sudo systemctl status docker

sudo service docker status
启动(start)、停止(stop)、重启(restart)、查看状态(status)等。

2.容器

2.1创建容器

创建并运行
sudo docker run -it ubuntu:latest /bin/bash

创建不运行
sudo docker run -it -d alpine:latest

运行容器
sudo docker attach d74f2ceb5f3a

docker exec -it 容器id /bin/bash
docker exec -it mycontainer /bin/bash
docker exec 相当于进入容器并开启一个新的终端,可以在里面操作。
如果使用exit退出,容器也不会停止。
docker attach 进入容器正在执行的终端,不会启动新的进程。
如果使用exit退出,容器会停止运行!

创建并命名
sudo docker run -it -d --name ostechnix_alpine alpine:latest
sudo docker run -it --name name ubuntu:latest /bin/bash

创建分配gpu

sudo docker run -it -d --name czc_tensorrt_2310 --gpus all --cpus 48 --shm-size 16G --memory 500gb \
-v /etc/localtime:/etc/localtime \
-v /data/Codes:/data/Codes \
-v /data/NFS:/data/NFS  nvcr.io/nvidia/tensorrt:23.10-py3
docker run --gpus all --cpus 48 --shm-size 16G --memory 500gb -itd \
-v /etc/localtime:/etc/localtime \
-v /data/Codes:/data/Codes \
-v /data/NFS:/data/NFS \
--name czc_triton2_2310 \
-p 8049:8001 \
-p 8059:8000 \
nvcr.io/nvidia/tritonserver:23.10-py3

docker exec 命令用于在正在运行的 Docker 容器中运行指定的命令。
docker exec [OPTIONS] CONTAINER COMMAND [ARG…]
其中,OPTIONS 可以省略,常用的选项如下:
-i:保持标准输入打开,使得可以与容器交互。
-t:分配一个伪终端,使得可以与容器交互。
CONTAINER 是要操作的容器的名称或 ID。
COMMAND 是要在容器内运行的命令。
ARG… 是命令的参数。
在名为 mycontainer 的容器中执行命令 /bin/bash 并分配一个伪终端:
docker exec -it mycontainer /bin/bash
在名为 mycontainer 的容器中执行命令 ls -l:
docker exec mycontainer ls -l

# 常用的参数
docker run -d -p  宿主机端口:容器端口 --name 容器名称 镜像的标识|镜像名称[tag]
# -d: 代表后台运行容器
# -p: 宿主机端口:容器端口: 为了映射当前Linux的端口和容器的端口
# --name 容器名称: 指定容器的名称

2.2查看容器

#查看运行
sudo docker ps
#列出所有可用的容器(运行或者停止)
sudo docker ps -a
#查看容器信息
docker inspect  <container id>
#查看容器Privileged权限是否开启
docker inspect --format='{{.HostConfig.Privileged}}' <container id>

2.3启动容器

启动start、重启restart、暂停pause 和终止容器stop
#名称或ID
sudo docker start modest_cray
sudo docker start 10615254bb45

容器脱离(不要退出)回到主机系统的 shell。不要终止或者关闭容器。使用 CTRL+P 然后 CTRL+Q 从容器中脱离,这样不会关闭容器。

删除容器
sudo docker rm 377e6d77ebb5

2.4创建容器脚本

#!/bin/bash

docker_run_name=$1
docker_image_name=$2
docker_image_version=$3
ssh_port=$4
jupyter_port=$5
tensorboard=$6


docker run --gpus all --cpus 48 --shm-size 16G --memory 500gb --privileged=true -itd \
  -p ${ssh_port}:22 \
  -p ${jupyter_port}:8888 \
  -p ${tensorboard}:6006 \
  -v /etc/localtime:/etc/localtime \
  -v /data/Codes:/data/Codes \
  -v /data/NFS:/data/NFS \
  --name ${docker_run_name} \
  -e JUPYTER_PASSWORD="123456" \
  -e JUPYTER_PORT=8888 \
  -e ROOT_PASS="123456" \
  ${docker_image_name}:${docker_image_version}


# bash create_pytorch_container.sh virtual_ngc_2306 nvcr.io/nvidia/pytorch 23.06-py3 8018 8019 8020
# bash create_pytorch_container.sh llama_efficient_pytorch_2306 nvcr.io/nvidia/pytorch 23.06-py3 8005 8006 8007
#
# bash create_pytorch_container.sh czc_test_ngc_2312 nvcr.io/nvidia/pytorch 23.12-py3 8066 8067 8068
# bash create_pytorch_container.sh czc_videointer_ngc_2312 nvcr.io/nvidia/pytorch 23.12-py3 8046 8047 8048

#添加--privileged=true
# bash create_pytorch_container.sh czc_sshcontainer_ngcpytorch_2312 nvcr.io/nvidia/pytorch 23.12-py3 8056 8057 8058

2.5Docker容器修改端口映射

参考:https://zhuanlan.zhihu.com/p/94949253
1.使用docker ps -a命令找到要修改容器的CONTAINER ID
2.运行以下命令,进入该容器目录
docker inspect【CONTAINER ID】| grep Id
cd /var/lib/docker/containers
停止容器
docker stop [容器id]
3.停止主机docker服务
systemctl stop docker
4.进入2得到的文件夹内,修改hostconfig.json 和 config.v2.json
5.保存之后重启docker服务和容器
systemctl start docker
docker start [docker id]

3、镜像

3.1查看镜像

sudo docker images
sudo docker search ubuntu
sudo docker pull ubuntu

3.2创建镜像

将容器变成镜像
sudo docker commit 377e6d77ebb5 ostechnix/ubuntu_apache
docker commit 7ca736d99653 yolov5:v6.2
移除容器
docker rm container_id
docker rm container_name

删除镜像
docker rmi [image] 或者:docker image rm [image]
docker rmi allen_mysql:5.7
docker rmi ee7cbd482336

3.3保持和加载镜像

参考:https://blog.csdn.net/qq_41204464/article/details/122034637
二、打包tar
使用save参数进行打包,格式如:docker save -o tar文件名称 镜像REPOSITORY:TAG

docker save -o yolov5-v6.2.tar yolov5:v6.2

其中yolov5:v6.2 是需要保存镜像的REPOSITORY、和TAG;也是上面保存的镜像名称。

三、加载tar镜像
使用load进行从tar文件导出镜像

docker load -i yolov5-v6.2.tar

然后查看是否出现镜像
docker images

3.4上传镜像到docker hub仓库

1、注册dockerhub: https://registry.hub.docker.com/
2、登录docker:docker login (CentOS系统docker服务中操作)
3、登出、退出: docker logout
4、tag修改镜像为仓库的规范才能推送
推送镜像的规范是:docker push 注册用户名/镜像名

tag命令修改为规范的镜像:
docker tag boonya/tomcat-allow-remote boonyadocker/tomcat-allow-remote

推送镜像的规范是:
docker push 注册用户名/镜像名

查看修改后的规范镜像:
docker images

5、推送镜像到Docker Hub
通过push命令推送镜像:

docker push boonyadocker/tomcat-allow-remote:latest

参考:https://blog.csdn.net/boonya/article/details/74906927

4、在宿主机和容器之间交换⽂件

在宿主机和容器之间相互COPY⽂件 cp的⽤法如下

# 容器中 复制到 宿主机
docker cp [OPTIONS] CONTAINER:PATH LOCALPATH 
eg:docker cp  tomcat-8081:/usr/local/tomcat/webapps/ROOT/index.jsp /root/

# 宿主机 复制到 容器中
docker cp [OPTIONS] LOCALPATH|- CONTAINER:PATH
eg:docker cp /root/index.html tomcat-8081:/usr/local/tomcat/webapps/ROOT/

复制文件
将当前目录tpch文件夹复制到mysql容器相应的位置:
docker cp tpch mysql56:/var/lib/mysql #mysql56为容器名
容器文件拷贝到宿主机:
docker cp 容器名:要拷贝的文件在容器里面的路径 要拷贝到宿主机的相应路径

Docker数据卷
通过镜像创建一个容器。容器一旦被销毁,则容器内的数据将一并被删除。但有些情况下,通过服务器上传的图片出会丢失。容器中的数据不是持久化状态的。这个时候可以通过数据卷来解决这个问题。https://zhuanlan.zhihu.com/p/430652941

5、docker 容器之间通信

菜鸟:https://www.runoob.com/docker/docker-container-connection.html
https://www.cnblogs.com/makalochen/p/14242125.html#%E7%AE%80%E4%BB%8B
我们安装Docker后,它会自动创建三个网络,bridge(创建容器默认连接到此网络)、 none 、host。
host:容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。
None:该模式关闭了容器的网络功能,相当于一个回环网络。
Bridge:此模式会为每一个容器分配、设置IP等,并将容器连接到一个叫docker0的虚拟网桥,通过docker0网桥以及Iptables nat表配置与宿主机通信。
以哪种方式让服务器内部的容器与公网进行通信。
1、假如使用的是默认的桥接网络模式,启动容器的时候需要使用参数-p 宿主机端口:容器端口设置端口的映射。
2、假如使用的是host主机模式,因为使用的是宿主机的ip与端口,那就直接可以与公网通信。

查看IP:
ip安装apt-get update & apt-get install -y iproute2
ip addr 或 ip a
或用ifconfig

5.1查看网络

docker network ls
docker network inspect NETWORKID

5.2创建网络

链接:https://blog.csdn.net/longjuanfengzc/article/details/89340391
https://blog.csdn.net/u013355826/article/details/84987233
1.默认创建容器时默认连接的是bridge,其实可以创建容器时可以指定使用的网络,可以指定host、none甚至可以自己建一个bridge
docker network create -d bridge my-bridge

2.通过link,使用link相当于使用DNS记录(不推荐)
通过busybox创建一个容器名为test1
docker run -d --name test1 busybox /bin/sh -c “while true; do sleep 3600; done”
再用busybox创建一个容器名为test2,创建test2时使用了link链接了test1
docker run -d --name test2 --link test1 busybox /bin/sh -c “while true; do sleep 3600; done”

5.3容器连接到网络

将容器连接到网络
docker run --net= …
或者将已存在容器加入新的网络
docker network connect

创建时指定网络
docker network create -d bridge my-bridge

启动容器并指定模式
默认是Bridge
在容器启动命令时用参数–net=host指定当前容器网络模式
如: docker run -itd --net=host centos:7 /bin/bash

5.4网络端口映射

参考:https://cloud.tencent.com/developer/article/1831540
外网如何访问容器?
端口映射,-p指定对应端口
外网访问容器用到了docker-proxy和iptables DNAT

  • 宿主机访问本机容器使用的是iptables DNAT
  • 外部主机访问容器或容器之间的访问是docker-proxy实现

可以通过 -P 或 -p 参数来指定端口映射。
当使用 -P 标记时,Docker 会随机映射一个 49000~49900 的端口到内部容器开放的网络端口。
-p (小写的)可以指定要映射的端口,并且,在一个指定端口上只可以绑定一个容器。
docker run -d -P training/webapp python app.py
使用 hostPort:containerPort 格式本地的 5000 端口映射到容器的 5000 端口,可以执行
docker run -d -p 5000:5000 training/webapp python app.py

5.5Docker的跨主机网络访问

跨主机网络解决方案
docker原生的overlay和macvlan
第三方的flannel、weave、calico

6、docker嵌套

docker --privileged=true 参数作用
大约在0.6版,privileged被引入docker。
使用该参数,container内的root拥有真正的root权限。
否则,container内的root只是外部的一个普通用户权限。
privileged启动的容器,可以看到很多host上的设备,并且可以执行mount。
甚至允许你在docker容器中启动docker容器。
链接:https://blog.csdn.net/wangxuelei036/article/details/107457712

方法1:共享宿主机 dockerd 服务
方法2:独立隔离的容器运行环境
方法3:使用 Sysbox 运行时
参考:https://www.zhaowenyu.com/docker-doc/dind/docker-in-docker.html

有关Docker容器内不能使用Systemctl等命令的解决方法
systemctl start mysql
System has not been booted with systemd as init system (PID 1). Can’t operate

解决方法
有两种

  • 使用service代替systemctl
    service mysql start

  • 赋予特权并在init中启动
    docker run -it --privileged=true -h node02 --ip 172.18.0.2 --name node02 ubuntu:v1 /usr/sbin/init
    链接:https://blog.csdn.net/weixin_43410596/article/details/121865128

解决办法:
运行容器时添加`--privileged=true`,修改/bin/bash为/sbin/init
[root@919 ~]# docker run -itd --name nginxv2 --privileged=true centos /usr/sbin/init 

验证:
powershell
[root@919 ~]# docker exec -it nginxv2 /bin/bash
[root@491ab139e4fd /]# systemctl start nginx

7、服务集群

参考:https://www.runoob.com/docker/docker-swarm.html
Docker Compose
Compose 项目是 Docker 官方的开源项目,负责实现对 Docker 容器集群的快速编排。使用前面介绍的Dockerfile我们很容易定义一个单独的应用容器。然而在日常开发工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器;再比如在分布式应用一般包含若干个服务,每个服务一般都会部署多个实例。如果每个服务都要手动启停,那么效率之低、维护量之大可想而知。这时候就需要一个工具能够管理一组相关联的的应用容器,这就是Docker Compose。

Docker Swarm是Docker官方提供的容器集群管理以及容器编排解决方案,Docker Swarm基于Docker Compose组件以及网络等基础能力,提供了服务编排、负载均衡、动态伸缩、滚动更新等能力。

Docker Engine:作为 Docker 镜像构建与容器化启动的工作引擎;
Docker Machine:安装与管理 Docker Engine 的工具;
Docker Swarm:是 Docker 自1.12后自带的集群技术,将多个独立的 Docker Engine 利用 Swarm 技术进行集群化管理;

8、显示GPU进程所属docker 容器

https://www.jianshu.com/p/df7b444c4153
nvidia-smi查看进程占用GPU情况PID
1、查看单个
通过docker ps 查看所有运行的容器,然后一个一个运行docker top containerId| grep PID,根据返回情况判断这个进程在哪个容器里面。比如 docker top d7c1 | grep 21274 ,返回为空,说明不在这个容器里面,接着再试直到找到容器为止。

docker top 15766f6eeaf7(容器ID)  | grep 55123(PID)

2、查看所有

#!/bin/bash
# find docker container by process id
processId=
# 提取程序的名字
PROGNAME=$(basename $0)
usage () {
    echo " $PROGNAME [-p --processId] or $PROGNAME"
    return
}
# 一个while case用来提取参数
while [[ -n $1 ]]; do
    case $1 in  
    -p | --processId) shift
                      processId=$1
                      ;;  
    -h | --help) usage
                 exit
                 ;;  
    *) usage >&2 
       exit 1
       ;;  
    esac
    shift
done

# 定义一个函数
findCon () {
    # $1 是函数的输入
    local pId=$1
    # awk '{print $1,$NF}' 打印第一列和最后一列,即容器ID和容器Name,awk 'NR != 1' 不打印第一行
    # read代表读入变量
    docker ps | awk '{print $1,$NF}' | awk 'NR != 1' | while read conId conName; do
                # 对pId的grep使用正则表达式,不然的话如果输入进程pId为21则会匹配到21274,通过前后加入空格匹配就可以防止出现这种问题
                local temp="[[:space:]]\{1\}${pId}[[:space:]]\{1\}"
                if [[ -n $(docker top $conId | grep -e $temp) ]]; then
                   printf "%s\t\t%s\t\t%s\t\t" $pId $conId $conName
                    break
                fi
            done
    return
}


# 如果 $processId不为空
if [[ -n $processId  ]]; then
    # 判断输入是否为数字
    if [[ $processId =~ ^[0-9]+$ ]]; then
        printf "conId%s\t\t\tconName%s\n" $conId $conName
        findCon $processId
    else
        echo "Please input number"
        exit 1
    fi
else
    num=1
   printf "PID\t\tconId%s\t\t\tconName%s\t\t\tGPU Memory\n" $conId $conName
    # 这一串awk操作为提取进程id和GPU使用情况,然后去掉空格,-F为设定awk分隔符,在命令行输出一边就看懂了
    nvidia-smi -q 2>&1| awk '/Process ID|Used GPU Memory/' | awk '{gsub(/[[:blank:]]*/,"",$0);print $0}' | awk -F ":" '{print $NF}' | while read item; do
    if [[ $(($num % 2)) != 0 ]]; then
        findCon $item
    else
        printf "%s\n" $item
    fi
    num=$((num+1))
    done
fi

在这里插入图片描述

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值