Docker 镜像和容器

2023-05-16

1. 安装配置

1.1 安装

# 卸载
sudo apt remove docker docker-engine docker.io

# docker.io: Debian 团队维护
sudo apt install docker.io

# docker-ce: 官方社区版
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
sudo apt update
apt-cache madison docker-ce
sudo apt install docker-ce=<VERSION>

# 免 sudo,重新登录后生效
sudo usermod -aG docker $USER
sudo systemctl restart docker

# 二进制包
https://download.docker.com/linux/static/stable

1.2 启动配置

mkdir -p /etc/docker

cat > /etc/docker/daemon.json <<EOF
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "insecure-registries" : [ "192.168.80.250:5000" ]
}
EOF

1.3 支持代理

mkdir -p /etc/systemd/system/docker.service.d

cat > /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF 
[Service] 
Environment="ALL_PROXY=socks5://192.168.31.20:1080/"
Environment="NO_PROXY=localhost,127.0.0.1,docker.io,hub.elihe.io,pvjhx571.mirror.aliyuncs.com"
EOF

systemctl daemon-reload && systemctl restart docker

1.4 远程访问

vi /etc/docker/daemon.json
{
    "hosts": ["tcp://0.0.0.0:2357", "unix:///var/run/docker.sock"]
}

# -H, --host
docker -H 192.168.31.41 network show

2. 镜像管理

2.1 基本操作

docker images

docker search nginx
docker pull nginx
docker rmi nginx

docker tag nginx nginx:v0.1
docker push nginx:v0.1

docker history nginx:v0.1


docker image prune      # 清理 dangling 镜像
docker image prune -a   # 清理所有没有关联容器的镜像

2.2 容器和镜像

  • export/import:容器文件化

  • save/load: 镜像文件化

  • commit: 容器镜像化

# image => file => image
docker save -o nginx.tar nginx
docker load -i nginx.tar

docker run --name nginx-server -p 8080:80 -d nginx
# docker exec -it nginx-server /bin/bash
root@02d9c2b750f6:/# echo "<h1>hello docker</h1>" > /usr/share/nginx/html/hello.html

# container => file => image
docker export -o nginx-server.tar nginx-server
docker import nginx-server.tar nginx:v0.2

# container => image
docker commit -p nginx-server nginx:v0.3    # -p, --pause

使用场景:

  • save & load: 适合 docker-compose.yml 编排的组合镜像,进行离线的迁移
  • export & import: 适合在基础镜像启动的容器中,安装了其他软件或服务后,将该容器导出,形成一个新的镜像。

文件的区别:

  • save: 是一个 docker 分层文件系统, 因为它由一层层文件系统叠加起来,存在很多重复的文件,所以较大
  • export: 是一个 Linux 系统文件目录

2.3 构建镜像

2.3.1 Dockerfile 指令

  • FROM: 指定基础镜像

    • 服务类镜像: nginxredismongomysqlhttpdphptomcat
    • 语言类镜像: nodeopenjdkpythonrubygolang
    • 操作系统镜像: ubuntudebiancentosfedoraalpine
    • 空白镜像:scratch 适用于静态编译的程序,不需要操作系统支撑。
  • MAINTAINER:

  • COPY: 复制文件

  • ADD: 支持添加URL,自动解压文件等

  • WORKDIR: 指定默认目录工作

  • RUN: 构建镜像时执行, 用于安装应用和软件包,创建用户等操作

  • ENTRYPOINT: 运行容器的入口命令, 但支持额外参数

  • CMD: 运行容器的启动命令。如果没有定义 ENTRYPOINT, CMD 将作为它的 ENTRYPOINT;如果定义了 ENTRYPOINT 的话,CMD 只为 ENTRYPOINT 提供参数;CMD 可由 docker run 后的命令覆盖,同时覆盖参数

  • ENV: 设置环境变量

  • VOLUME: 定义匿名卷

  • EXPOSE: 曝露端口

  • USER:指定当前用户

  • HEALTHCHECK

2.3.2 scratch镜像

golang程序:静态编译

mkdir -p scratch && cd $_

cat > hello.go <<EOF
package main
import "fmt"

func main() {
    fmt.Println("hello world")
}
EOF

cat > Dockerfile <<EOF
FROM golang as builder
WORKDIR /go/src/app
COPY hello.go .
RUN go build -ldflags="-w -s" hello.go

FROM scratch
COPY --from=builder /go/src/app/hello /
CMD ["/hello"]
EOF

docker build -t hello .
docker run --rm hello 

2.3.3 示例:构建Nginx镜像

$ mkdir -p nginx && cd $_

$ vi index.html
<h1>hello world!</h1>

$ vi entrypoint.sh
#!/bin/sh

cat > /etc/nginx/conf.d/default.conf <<EOF
server {
    listen ${IP:-0.0.0.0}:${PORT:-80};
    server_name $HOSTNAME;
    
    location / {
        root   ${WEB_ROOT:-/usr/share/nginx/html};
        index  index.html index.htm;
    }
}
EOF

exec "$@"
#+++++++++++++++++++++++++++++++++++++++++++

$ vi Dockerfile
FROM nginx:1.19.2-alpine
LABEL maintainer="eli.he@live.cn"

ENV WEB_ROOT="/data/www/html/"
WORKDIR $WEB_ROOT

ADD index.html ./
ADD entrypoint.sh /bin/

RUN chmod +x /bin/entrypoint.sh
EXPOSE 80/tcp
HEALTHCHECK --start-period=3s CMD curl -o - -q http://${IP:-0.0.0.0}:${PORT:-80}

CMD ["/usr/sbin/nginx", "-g", "daemon off;"]
ENTRYPOINT ["/bin/entrypoint.sh"]
#+++++++++++++++++++++++++++++++++++++++++++

$ docker build -t web:1.0 .
$ docker run -p 8080:80 -d web:1.0

2.3.4 易错点

  • 错误的文件系统操作

    在 Shell 中,连续两行是同一个进程执行环境,因此前一个命令修改的内存状态,会直接影响后一个命令;而在 Dockerfile 中,这两行 RUN 命令的执行环境根本不同,是两个完全不同的容器。

    RUN cd /app
    RUN echo "hello" > world.txt  # 文件并不在/app目录下
    
  • docker中的进程,必须以前台方式启动

    对于容器而言,其启动程序就是容器应用进程,容器就是为了主进程而存在的,主进程退出,容器就失去了存在的意义,从而退出,其它辅助进程不是它需要关心的东西。

    CMD echo $HOME
    CMD ["sh", "-c", "echo $HOME"] # 实际执行命令
    
    # 错误的示范
    CMD service nginx start
    CMD ["sh", "-c", "service nginx start"] # 实际执行命令
    
    # 正确的nginx启动命令, 必须以前台形式运行
    CMD ["nginx", "-g", "daemon off"]
    
  • 支持额外参数

    CMD ["curl", "-s", "https://cip.cc"]         # 不主持额外参数
    ENTRYPOINT ["curl", "-s", "https://cip.cc"]  # 支持额外参数,docker run --rm myip -i   获取HTTP请求头,但这里报错,无法将该参数传入
    

2.4 特殊镜像

2.4.1 虚悬镜像

仓库名、标签均为 的镜像 (docker pull/build 时,原有的镜像名被占用,会导致此种情况)

$ docker images -f dangling=true
REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
<none>       <none>    06ebe39c8aee   11 minutes ago   22.1MB
<none>       <none>    62c8bc68a9ed   33 minutes ago   942MB

$ docker image prune  # 删除虚悬镜像

2.4.2 中间层镜像

为了加速镜像构建、重复利用资源,Docker 会利用 中间层镜像

$ docker images -a

3. 容器管理

img

3.1 基本操作

docker create --name myweb -p 8080:80 nginx
docker start myweb
docker stop myweb
docker pause myweb
docker unpause myweb

docker ps
docker kill myweb
docker rm myweb

# Ctrl+P Ctrl+Q 切换到后台运行, 变成守护式容器
docker run --name test -it busybox /bin/sh
docker attach test   # Attach local standard input, output, and error streams to a running container, exit后,容器自动停止

# 守护式容器, 适合有常驻进程的镜像
docker run --name myweb -p 8080:80 -d nginx
docker exec -it myweb /bin/sh

docker logs -tf --tail=10 myweb  # 查看容器日志. -f --follows, -t --timestamps
docker inspect myweb

docker port myweb
docker top myweb     # 容器进程
docker stats myweb   # 实时监控,相当于进入容器执行 top

# 宿主机与容器的文件拷贝
docker cp myweb:/usr/share/nginx/html/50x.html .
docker cp index.html myweb:/usr/share/nginx/html/

3.2 资源限制

docker run --cpu-shares=512     # -c, 50% CPU, 1024 means 100% of the CPU
docker run --cpuset-cpus=0,2,4  # 使用0,2,4三个 CPU

docker run --memory 300M        # -m

3.3 访问宿主机

# Mount a FUSE based fs
docker run --rm -it --cap-add SYS_ADMIN --device /dev/fuse sshfs

# give access to a single device
docker run -it --device=/dev/ttyUSB0 ubuntu /bin/sh

# 获取宿主机root权限
docker run -it --privileged -v /dev/bus/usb:/dev/bus/usb ubuntu /bin/sh

3.4 容器诊断

# 保存案发现场
docker commit 05dd6f84ddf9 user/debug

# 以命令行方式启动
docker run -it --rm user/debug /bin/sh

docker run --rm --entrypoint="" grafana/grafana:latest /bin/sh -c 'cat /etc/passwd | grep grafana'

3.5 容器自动启动

# 创建容器时
docker run --restart=always

# 容器运行时更新
docker update --restart=always 07fb7442f813

--restart 参数值:

  • no: 不自动重启,默认值
  • on-failure: 容器错误退出,即退出码不为0时,重启容器
  • always:容器停止,自动重启。如果手动停止,需要重启dockerd进程或者重启容器本身才生效。主要用于宿主机重启后,自动启动容器
  • unless-stopped:同always,但当手动停止,即使重启dockerd进程,也无法自动启动容器

4. 资源清理

docker kill $(docker ps -aq)

docker rm $(docker ps -aq)
docker rm -v $(docker ps -aq -f status=exited)         # 删除所有已退出的容器
docker rm -v $(docker ps -aq -f status=dead)           # 删除所有状态为dead的容器

docker rmi $(docker images -q)
docker volume rm $(docker volume ls -q)
docker volume rm $(docker volume ls -qf dangling=true) # 删除所有未被容器引用的卷

docker system df        # 存储统计
docker system df -v
docker system prune     # 空间自动清理
docker system prune -a  # 一并清除所有未被使用的镜像和悬空镜像
docker system prune -f
docker images -f dangling=true   # 悬空镜像

5. 常用镜像

docker pull mysql:5.7
docker run --name mysql-server -p 3306:3306 -v /data/mysql/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

docker pull redis:6.0.10
docker run --name reids-server -p 6379:6379 -d redis:6.0.10

docker pull elasticsearch:7.16.3
docker run --name es -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d elasticsearch:7.16.3

6. 使用技巧

6.1 输出控制

$ docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Ports}}"
CONTAINER ID   NAMES     PORTS
6c30d12fadaf   nexus3    0.0.0.0:8081->8081/tcp, :::8081->8081/tcp
名称含义
.ID容器ID
.Image镜像ID
.Command执行的命令
.CreatedAt容器创建时间
.RunningFor运行时长
.Ports暴露的端口
.Status容器状态
.Names容器名称
.Label分配给容器的所有标签
.Mounts容器挂载的卷
.Networks容器所用的网络名称
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Docker 镜像和容器 的相关文章

随机推荐

  • 【数组】顺时针打印矩阵

    题目 输入一个矩阵 xff0c 按照从外向里以顺时针的顺序依次打印出每一个数字 xff0c 例如 xff0c 如果输入如下4 X 4矩阵 xff1a 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出
  • 【数组】数组中出现次数超过一半的数字

    题目描述 数组中有一个数字出现的次数超过数组长度的一半 xff0c 请找出这个数字 例如输入一个长度为9的数组 1 2 3 2 2 2 5 4 2 由于数字2在数组中出现了5次 xff0c 超过数组长度的一半 xff0c 因此输出2 如果不
  • java for循环的几种写法

    参考 xff1a https blog csdn net qq 36804363 article details 87539927 span class token keyword int span span class token pun
  • 【双指针】和为S的两个数字

    题目描述 输入一个递增排序的数组和一个数字S xff0c 在数组中查找两个数 xff0c 使得他们的和正好是S xff0c 如果有多对数字的和等于S xff0c 输出两个数的乘积最小的 输入 1 2 4 7 11 15 15 返回值 4 1
  • 【动态规划】连续子数组的最大和

    题目描述 输入一个整型数组 xff0c 数组里有正数也有负数 数组中的一个或连续多个整数组成一个子数组 求所有子数组的和的最大值 要求时间复杂度为 O n 输入 xff1a 1 2 3 10 4 7 2 5 返回值 xff1a 18 说明
  • Java交换字符串中两个位置的值

    需求 xff1a 对一字符串abcd xff0c 要求交换位置0和位置2的两个字符 xff0c 交换结果为cbad java高效实现方案 xff0c 先将String转换为char数组 xff0c 数组可以修改任意位置的值 xff0c 进行
  • 【动态规划、递归回溯】字符串的排列

    题目描述 输入一个字符串 按字典序打印出该字符串中字符的所有排列 例如输入字符串abc 则按字典序打印出由字符a b c所能排列出来的所有字符串abc acb bac bca cab和cba 输入一个字符串 长度不超过9 可能有字符重复 字
  • 【数组】把数组排成最小的数

    题目描述 输入一个正整数数组 xff0c 把数组里所有数字拼接起来排成一个数 xff0c 打印能拼接出的所有数字中最小的一个 例如输入数组 3 xff0c 32 xff0c 321 xff0c 则打印出这三个数字能排成的最小数字为32132
  • Docker 容器介绍

    1 简介 1 1 容器和VM 什么是容器 xff1a 一种操作系统级别的虚拟化的方案只能运行相同或相似内核的操作系统依赖Linux内核特性 xff1a Namespace和Cgroups 1 2 依赖内核特性 Namespaces xff1
  • 【数组】数组中重复的数字

    题目描述 在一个长度为n的数组里的所有数字都在0到n 1的范围内 数组中某些数字是重复的 xff0c 但不知道有几个数字是重复的 也不知道每个数字重复几次 请找出数组中第一个重复的数字 例如 xff0c 如果输入长度为7的数组 2 3 1
  • 【数组】构建乘积数组

    题目描述 给定一个数组A 0 1 n 1 请构建一个数组B 0 1 n 1 其中B中的元素B i 61 A 0 A 1 A i 1 A i 43 1 A n 1 不能使用除法 xff08 注意 xff1a 规定B 0 61 A 1 A 2
  • 【二分法】数字在升序数组中出现的次数

    题目描述 统计一个数字在升序数组中出现的次数 示例1 输入 1 2 3 3 3 3 4 5 3 返回值 4 看到数组是有序的 xff0c 并且是查找 xff0c 应该想到用二分法 xff0c 最简单的方法是用二分法找到该数 xff0c 然后
  • 【字符串】第一个只出现一次的字符

    题目描述 在一个字符串 0 lt 61 字符串长度 lt 61 10000 xff0c 全部由字母组成 中找到第一个只出现一次的字符 并返回它的位置 如果没有则返回 1 xff08 需要区分大小写 xff09 xff08 从0开始计数 xf
  • 【字符串】左旋转字符串

    题目描述 汇编语言中有一种移位指令叫做循环左移 xff08 ROL xff09 xff0c 现在有个简单的任务 xff0c 就是用字符串模拟这个指令的运算结果 对于一个给定的字符序列S xff0c 请你把其循环左移K位后的序列输出 例如 x
  • 【字符串】翻转单词顺序列

    题目描述 牛客最近来了一个新员工Fish xff0c 每天早晨总是会拿着一本英文杂志 xff0c 写些句子在本子上 同事Cat对Fish写的内容颇感兴趣 xff0c 有一天他向Fish借来翻看 xff0c 但却读不懂它的意思 例如 xff0
  • 【数组】扑克牌顺子

    题目描述 LL今天心情特别好 因为他去买了一副扑克牌 发现里面居然有2个大王 2个小王 一副牌原本是54张 他随机从中抽出了5张牌 想测测自己的手气 看看能不能抽到顺子 如果抽到的话 他决定去买体育彩票 嘿嘿 xff01 xff01 红心A
  • 【torch.einsum】

    参考 xff1a https www cnblogs com mengnan p 10319701 html 爱因斯坦简记法 xff0c 能简洁表示各种矩阵向量的操作 xff0c 例如矩阵转置 乘法 求和等等 xff0c pytorch中调
  • Linux关闭指定GPU进程

    首先查看正在运行的GPU进程 span class token function watch span n 1 nvidia smi 查看GPU进程PID 使用命令kill 9 PID关闭进程 xff0c 多个进程则PID之间用空格隔开 x
  • 【字符串】字符流中第一个不重复的字符

    题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符 例如 xff0c 当从字符流中只读出前两个字符 34 go 34 时 xff0c 第一个只出现一次的字符是 34 g 34 当从该字符流中读出前六个字符 google 34 时
  • Docker 镜像和容器

    1 安装配置 1 1 安装 span class token comment 卸载 span span class token function sudo span span class token function apt span re