docker随笔
docker
一、docker简介
Docker 是一个开源的容器化平台,它彻底改变了应用程序的开发、部署和运行方式。通过 Docker,开发者可以将应用程序及其所有依赖打包进一个轻量级、可移植的容器中。这些容器包含了运行应用程序所需的一切,从代码、运行时环境、库到配置文件,确保了应用在不同环境间的一致性,无论是开发者的桌面、测试服务器还是最终的生产环境。
二、docker的基础组成部分
- images
- container
- repository
2.1 images
Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。
docker镜像通过分层存储的方式进行存储。
2.1.1 分层存储
docker image 构建是一层层的构建,每一层相对来说都是独立。每一层构建完成后都不会在发生改变,第一层构建完成,第二层删除第一层,事实上并不会真的删除,相当于对第一层进行一个标记,不会使用第一层。分层存储使得image的构建和服用都变得更加容易些。
2.2 container
container 与image的关系,image是静态的,container是动态的。从java 对象的角度来看,image相当于 java中的类,而container相当于 实例后的对象。container可以进行删除、停止等操作。对于container,同样是采用了分层存储,容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 [命名空间 。容器拥有自己的 root 文件系统(根目录文件系统)、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来。对于使用container过程中产生的数据,最好是建立数据卷或者与宿主机目录进行绑定,不要放在容器的存储层中。
2.3 repository
就像一个image托管平台,可以进行image上传和下载。
三、docker镜像使用
- 镜像获取
- 列出镜像
- 删除镜像
3.1 镜像获取
可以从docker hub 中获取官方制作的image
通过git pull 指令获取image 使用 指令+ --help 可以获得提示文档
root@lss-virtual-machine:~# docker pull --help
# 获得提示文档
Usage: docker pull [OPTIONS] NAME[:TAG|@DIGEST]
# 这里还可以指定 从哪一个registry[registryaddr ip:port]中获取image,如果没有制定,则默认是docker hub
Download an image from a registry
# 通常是从docker hub中获取
Aliases:
docker image pull, docker pull
# 这两个指令等价
Options:
-a, --all-tags Download all tagged images in the repository
# 获取一个镜像的各个版本,如果使用的话 可能会下载大量的image,占用硬盘空间
--disable-content-trust Skip image verification (default true)
# 不进行安全性验证
--platform string Set platform if server is multi-platform capable
# 制定系统的架构
-q, --quiet Suppress verbose output
# 让输出的日志信息更简洁
---------------------------------拉去mysql image--------------------------------
root@lss-virtual-machine:~# docker pull mysql
Using default tag: latest
latest: Pulling from library/mysql
72a69066d2fe: Pull complete
93619dbc5b36: Pull complete
99da31dd6142: Pull complete
626033c43d70: Pull complete
37d5d7efb64e: Pull complete
ac563158d721: Pull complete
d2ba16033dad: Pull complete
688ba7d5c01a: Pull complete
00e060b6d11d: Pull complete
1c04857f594f: Pull complete
4d7cfa90e6ea: Pull complete
e0431212d27d: Pull complete
Digest: sha256:e9027fe4d91c0153429607251656806cc784e914937271037f7738bd5b8e7709
Status: Downloaded newer image for mysql:latest
docker.io/library/mysql:latest
# 从这里也可以看出 image 是分层存储的。
3.2 镜像显示
镜像下载后可以通过docker images 命令查看顶层镜像,包括镜像id、镜像名、镜像占用的空间。具体的使用如下
root@lss-virtual-machine:~# docker image ls --help
Usage: docker image ls [OPTIONS] [REPOSITORY[:TAG]]
List images
Aliases:
docker image ls, docker image list, docker images
# 列举出镜像的 命令别名
Options:
-a, --all Show all images (default hides intermediate images)
# 会显示 非顶层的image (image采用分层存储)
--digests Show digests
# 同时会显示摘要信息 加密方法
-f, --filter filter Filter output based on conditions provided
--format string Format output using a custom template:
# 可以对于显示的属性进行格式化
'table': Print output in table format with column headers (default)
'table TEMPLATE': Print output in table format using the given Go template
'json': Print in JSON format
'TEMPLATE': Print output using the given Go template.
Refer to https://docs.docker.com/go/formatting/ for more information about formatting
output with templates
--no-trunc Don't truncate output
-q, --quiet Only show image IDs
# 只显示image id
-----------------------------------docker images示例----------------------------------
root@lss-virtual-machine:~# docker image ls -a
REPOSITORY TAG IMAGE ID CREATED SIZE
redis latest 1a83fd5edeed 4 days ago 117MB
quay.io/minio/minio latest 49c3911c1fe9 2 weeks ago 160MB
hello-world latest d2c94e258dcb 13 months ago 13.3kB
ccr.ccs.tencentyun.com/dockerpracticesig/docker_practice vuepress 5ea504439e5d 23 months ago 46MB
mysql latest 3218b38490ce 2 years ago 516MB
nacos/nacos-server latest bdf60dc2ada3 2 years ago 1.05GB
# 分别会显示 image_name version image_id created_time size
------------------------------------------进行格式化输出设置-----------------------------------------
root@lss-virtual-machine:~# docker image ls --format "table {{.Repository}}\t {{.ID}}\t{{.Size}}"
REPOSITORY IMAGE ID SIZE
redis 1a83fd5edeed 117MB
quay.io/minio/minio 49c3911c1fe9 160MB
hello-world d2c94e258dcb 13.3kB
ccr.ccs.tencentyun.com/dockerpracticesig/docker_practice 5ea504439e5d 46MB
mysql 3218b38490ce 516MB
nacos/nacos-server bdf60dc2ada3 1.05GB
# table 模板语法 docker image list --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}\t{{.Size}}"
# 常用的模板字段
#这里是一些常用的模板字段:
#.Repository: 镜像的仓库名
#.Tag: 镜像的标签
#.ID: 镜像的短ID
#.CreatedAt: 镜像创建时间
#.Size: 镜像大小
#
3.3 镜像删除
关于镜像删除可以使用docker image rm 相应的用法如下
root@lss-virtual-machine:~# docker image rm --help
Usage: docker image rm [OPTIONS] IMAGE [IMAGE...]
Remove one or more images
Aliases:
docker image rm, docker image remove, docker rmi
# 命令别名
Options:
-f, --force Force removal of the image
# 强制删除
--no-prune Do not delete untagged parents
# 不删除 没有打标签的 父镜像(标签:相当于给镜像起一个别名,一个镜像可以有多个标签)
镜像删除
root@lss-virtual-machine:~# docker image rm -f hello-world:latest
# 用于存在容器引用该镜像 所以需要-f 强制删除
Untagged: hello-world:latest
Untagged: hello-world@sha256:266b191e926f65542fa8daaec01a192c4d292bff79426f47300a046e1bc576fd
Deleted: sha256:d2c94e258dcb3c5ac2798d32e1249e42ef01cba4841c2234249495f87264ac5a
从删除的日志中可以看出,删除一个镜像需要先去除标签,在进行删除。这样做的原因是当删除了所有的tag这个时候该镜像没用了存在的意义(在docker中,是通过tag来引用和识别一个镜像的),同时也会触发delete这个动作,才可以去删除这个镜像。删除镜像可以通过 摘要信息和image id 或者 image name
3.4 使用commit
使用docker 获取镜像,一般是从dockerhub上获取,有时候获取不到满足自己需求又或者是需要在原有镜像上进行修改,可以使用commit,来修改镜像。
# 运行nginx
root@lss-virtual-machine:~# docker run -d -p 81:80 --name nginx nginx
4ca62905c9b747280276c1fb03e2cb23aa2beda795342d2308a01e4eda77070d
root@4ca62905c9b7:/# echo '<h1>hello world<h1>' > /usr/share/nginx/html/index.html
root@4ca62905c9b7:/# exit
exit
root@lss-virtual-machine:~# docker restart nginx
nginx
# 这时候nginx的index.html 内容就会发生改变
如果没有指定 卷的时候,容器在镜像的基础上,再添加一个数据存储层,用来存放容器的相关数据
如果想要保存当前状态,并生成一个镜像可以使用docker commit 命令(此时这个镜像就是在原有镜像的基础上加上改变)
# docker commit 语法
Usage: docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
Create a new image from a container's changes
Aliases:
docker container commit, docker commit
Options:
-a, --author string Author (e.g., "John Hannibal Smith <hannibal@a-team.com>")
# 声明作者
-c, --change list Apply Dockerfile instruction to the created image
-m, --message string Commit message
# 提交信息
-p, --pause Pause container during commit (default true)
# 提交的时候会默认暂停 container
-----------------------docker diff ----------------------------------------
# 通过该指令可以查询docker 容器的文件变化
# a add 添加
# d delete 删除
# c change 改变
root@lss-virtual-machine:~# docker diff nginx
C /root
A /root/.bash_history
C /usr
C /usr/share
C /usr/share/nginx
C /usr/share/nginx/html
C /usr/share/nginx/html/index.html
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /run
A /run/nginx.pid
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
docker commit 使用
root@lss-virtual-machine:~# docker commit --author "lss" --message "change msg" nginx nginx:latest
sha256:5cd82b3d2d8460868f651e18f886e5a92120015ca03b48b859b1490433e9e58f
# 使用docker images
root@lss-virtual-machine:~# docker images --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
5cd82b3d2d84 nginx latest
1a83fd5edeed redis latest
49c3911c1fe9 quay.io/minio/minio latest
5ea504439e5d ccr.ccs.tencentyun.com/dockerpracticesig/docker_practice vuepress
055129e7fec5 ccr.ccs.tencentyun.com/dockerpracticesig/docker_practice latest
605c77e624dd nginx <none>
3218b38490ce mysql latest
bdf60dc2ada3 nacos/nacos-server latest
从中可以看到 有一个nginx的tag 为none,也就是保存的镜像。
使用docker commit 保存镜像,会带来一些问题,自己制作的image 对于他人来说完全是黑箱的,除了开发者以外,很难对image进行开发和维护,docker diff 可以看出很多的文件都会被修改,虽然至改了一行代码。由于分层的理念,其他层并不会被改动。
3.5 DockerFile使用
先长一个坑,后面在来填。
四、docker容器操作
docker容器 是一个独立运行的应用,拥有自己的运行态环境,包括网络、文件系统等
4.1 容器创建
创建容器的指令 是 docker run
详细用法介绍:
Usage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Create and run a new container from an image
Aliases:
docker container run, docker run
Options:
--add-host list Add a custom host-to-IP mapping (host:ip)
# 进行自定义ip映射
-a, --attach list Attach to STDIN, STDOUT or STDERR
-c, --cpu-shares int CPU shares (relative weight)
--cpus decimal Number of CPUs
--cpuset-cpus string CPUs in which to allow execution (0-3, 0,1)
--cpuset-mems string MEMs in which to allow execution (0-3, 0,1)
-d, --detach Run container in background and print container ID
# 允许后台运行
--disable-content-trust Skip image verification (default true)
-e, --env list Set environment variables
# 设置环境变量
--env-file list Read in a file of environment variables
--expose list Expose a port or a range of ports
--gpus gpu-request GPU devices to add to the container ('all' to pass all GPUs)
--help Print usage
-h, --hostname string Container host name
--init Run an init inside the container that forwards signals and reaps processes
-i, --interactive Keep STDIN open even if not attached
# 与容器进行交互
-m, --memory bytes Memory limit
--mount mount Attach a filesystem mount to the container
# 文件系统挂载
--name string Assign a name to the container
# 设置容器名字
--network network Connect a container to a network
--network-alias list Add network-scoped alias for the container
# 设置网络别名
--rm Automatically remove the container when it exits
# 容器的生命随着容器的结束而删除
-v, --volume list Bind mount a volume
# 卷相关
--volume-driver string Optional volume driver for the container
--volumes-from list Mount volumes from the specified container(s)
-w, --workdir string Working directory inside the container
docker run --rm ubuntu /bin/echo 'hhh'
Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
7b1a6ab2e44d: Pull complete
Digest: sha256:626ffe58f6e7566e00254b638eb7e0f3b11d4da9675088f4781a50ae288f3322
Status: Downloaded newer image for ubuntu:latest
hhh
docker run 指令 新建一个容器的流程:
1.会先判断本地有没有该image,如果没有会从registry上下载
2.创建一个镜像并启动一个容器
3.分配一个文件系统、网络配置(可以自己设置)
4.正常执行,直至结束。
启动容器
可以使用docker start id|name
终止容器
当一个容器处于运行的时候可以使用docker stop [id|name]进行终止容器的操作
后台运行
docker run -d 可以让容器的输出信息不显示到宿主机上
root@lss-virtual-machine:~# docker run -d ubuntu /bin/sh -c "while true; do echo hello world; sleep 1; done"
b21ec3855d3721bc446b6880b56ebae45437d00e20eb81e2a80ce46715eab908
# 可以通过docker logs 查看
root@lss-virtual-machine:~# docker logs b21
hello world
hello world
hello world
hello world
hello world
hello world
进入容器内
docker exec 可以进入容器内进行命令行操作
Usage: docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
Execute a command in a running container
Aliases:
docker container exec, docker exec
Options:
-d, --detach Detached mode: run command in the background
--detach-keys string Override the key sequence for detaching a container
-i, --interactive Keep STDIN open even if not attached
# 可以进行命令行交互式操作
--privileged Give extended privileges to the command
-t, --tty Allocate a pseudo-TTY
# 分配一个伪终端
-----------------------------------示例-----------------------------------------
root@lss-virtual-machine:~# docker exec -it b21 ls
bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var
删除容器
可以使用docker rm 容器
Usage: docker rm [OPTIONS] CONTAINER [CONTAINER...]
Remove one or more containers
Aliases:
docker container rm, docker container remove, docker rm
Options:
-f, --force Force the removal of a running container (uses SIGKILL)
# 强制删除包括运行中的
-l, --link Remove the specified link
-v, --volumes Remove anonymous volumes associated with the container
查看容器
可以使用docker ps 查看正在运行的容器 加上 -a 参数能够查看所有的容器 这个相关操作与docker images差不多
也可以加上过滤条件和输出结果格式化
五、docker数据管理
docker数据管理主要侧重于docker内部 与 容器之间的数据管理,也可以说是对docker使用过程中生成的数据进行持久化
- volume
- mount
5.1 数据管理
docker 容器是建立在only read 镜像层的基础上,添加了一层可以进行读写的容器层。如果后期该容器不存在了,在容器中的存储的数据也会随之消失。使用 volume 或者 mount 可以对容器在读写过程中,产生的数据进行持久化到主机上。
-
volumes:由 Docker(/var/lib/docker/volumes/在 Linux 上)管理的主机文件系统的一部分中。非 Docker 进程不应修改文件系统的这一部分。卷是在 Docker 中持久化数据的最佳方式
特性:
- 数据卷中的内容可以在多个容器内使用
- 只能有docker进程修改
数据卷创建:
root@lss-virtual-machine:/var/lib/docker# docker volume create my-volume
my-volume
root@lss-virtual-machine:/var/lib/docker# cd volumes/
# 创建的数据卷默认位置在 /var/lib/docker/volumes 目录下
root@lss-virtual-machine:/var/lib/docker/volumes# ll
总计 36
drwx-----x 3 root root 4096 5月 28 21:19 ./
drwx--x--- 12 root root 4096 5月 28 17:53 ../
brw------- 1 root root 8, 3 5月 28 17:53 backingFsBlockDev
-rw------- 1 root root 32768 5月 28 21:19 metadata.db
drwx-----x 3 root root 4096 5月 28 21:19 my-volume/
---------------------------------查看volume信息---------------------------------------
root@lss-virtual-machine:/var/lib/docker/volumes# docker volume inspect my-volume
[
{
"CreatedAt": "2024-05-28T21:19:48+08:00",
"Driver": "local",
# 使用的存储驱动
"Labels": null,
# 标签 可以用来进行过滤
"Mountpoint": "/var/lib/docker/volumes/my-volume/_data",
# 在宿主机中实际的挂载点
"Name": "my-volume",
# 卷 名
"Options": null,
# 一些可选的信息
"Scope": "local"
# 作用范围
}
]
容器挂载数据卷
在使用docker run 命令的时候可以制定参数 --mount 或者 -v 进行将数据卷挂载到容器的挂载点上
root@lss-virtual-machine:/var/lib/docker/volumes# docker run -d -P --name nginx-test -v my-volume:/usr/share/nginx/html nginx
# run images 同时制定端口 有docker 进行自动的分配
# 端口号可以使用 docker port id|name 进行查询
2c5a608bf323a8e2f9387d0437f1ed77ac556bd2090b5077334e2d6c58ba551b
root@lss-virtual-machine:/var/lib/docker/volumes# docker exec -it nginx-test /bin/bash
root@2c5a608bf323:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
root@2c5a608bf323:/# cd /usr/share/nginx/html/
root@2c5a608bf323:/usr/share/nginx/html# cd ..
root@2c5a608bf323:/usr/share/nginx# ls
html
root@2c5a608bf323:/usr/share/nginx#
删除数据卷
docker volume rm my-volume
- bind mounts:可以存储在主机系统的任何位置。它们甚至可能是重要的系统文件或目录。Docker 主机或 Docker 容器上的非 Docker 进程可以随时修改它们。
bind mount 与数据卷的操作差不多,不同的是 挂载点可以任意位置,可以bind 一个或者多个文件。
root@lss-virtual-machine:/opt# docker run -d -P \
> --mount type=bind,source=/opt,target=/usr/share/nginx/html \
# source 可以是文件夹也可以是单个文件
> nginx
0ab82fbe817d68adbc773ac45a5fe6e5f6c65f8a8ec9b5024a6279f9abe53329
- tmpfs mounts:挂载仅存储在主机系统的内存中,永远不会写入主机系统的文件系统
总得来看,所谓的docker数据管理,就是将docker 容器运行时的数据进行保存,主要通过volume 和 mount 两种方式将数据持久化到磁盘上。
六、网络连接
docker运行的容器允许通过网络进行通信。
6.1运行容器制定网络设置
运行一个容器,指定端口有多种方式
root@lss-virtual-machine:/# docker run -it \
#> -P \ -P 自动的分配端口
#> -p 2345:80 \ 手动指定端口
> --name test-nginx \
> nginx
---------------------------查询端口信息------------------------------------
docker port
Usage: docker port CONTAINER [PRIVATE_PORT[/PROTO]]
List port mappings or a specific mapping for the container
Aliases:
docker container port, docker port
6.2 docker网络设置
七、DockerFile 与 docker compose
- DockerFile docker的一种文件,用来快速构建容器
- compose 通过yaml 模板文件来实现多个容器的互联,或者说构建一个完整的项目
7.1 DockerFile基础
docker file 是一个文本文件,里面放置docker可以执行的语句,用来构建自定义的镜像
使用dockerfile 定制一个镜像
root@lss-virtual-machine:/opt/mydockerfile# cat DockerFile
from nginx
# 以nginx镜像为基础
run echo "hello dockerfile" > /usr/share/nginx/html/index.html
# run命令会创建一个数据层
root@lss-virtual-machine:/opt/mydockerfile#
------------------------------构建镜像------------------------------------
root@lss-virtual-machine:/opt/mydockerfile# docker build -t nginx:v1 -f /opt/mydockerfile/DockerFile .
# -f 手动指定 dockerfile的位置 不加-f 默认在上下文路径 寻找Dockerfile文件[注意区分大小写]
# 执行语句中的 [.] 表示当前的上下文路径是当前目录。
# 上下文路径是由于执行docker build 命令需要由docker server来执行,对于docker server并不知道dockerfile文件的路径以及其他文件的位置,所以通过上下文路径来指定路径
[+] Building 0.5s (6/6) FINISHED docker:default
=> [internal] load build definition from DockerFile 0.0s
=> => transferring dockerfile: 111B 0.0s
=> [internal] load metadata for docker.io/library/nginx:latest 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [1/2] FROM docker.io/library/nginx:latest 0.0s
=> [2/2] RUN echo "hello dockerfile" > /usr/share/nginx/html/index.html 0.4s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:bd4ebed8e9ed2abf4b2b661722e602968ef287bcd18aa4d13e0f0ec74ade3832 0.0s
=> => naming to docker.io/library/nginx:v1 0.0s
Use 'docker scan' to run Snyk tests against images to find vulnerabilities and learn how to fix them
root@lss-virtual-machine:/opt/mydockerfile#
暂时感觉这些应该就差不多了,等以后用到了更多的地方在接着写。
7.2compose基础使用
等以后在填坑
compose建立在服务与项目的基础上,项目是由一个或多个服务组成,服务指的是一个个镜像,更多的是有dockerfile定制的镜像。使用compose可以很好搭建出一个项目,方便移植。
对于compose来说,更多的是用来构建项目,方便打包和移植。
compose 简单示例
------------------------------配置dockerfile文件---------------------------
FROM python:3.6-alpine
ADD . /code
# 将当前目录下的内容复制到 容器内部的code目录下
WORKDIR /code
# 工作目录 后续操作在该目录下完成
RUN pip install redis flask
CMD ["python", "app.py"]
# 以shell的形式执行
---------------------------------执行的web代码------------------------------------
from flask import Flask
from redis import Redis
# 简单的web项目 实现每次访问次数加一
app = Flask(__name__)
redis = Redis(host='redis', port=6379)
@app.route('/')
def hello():
count = redis.incr('hits')
return 'Hello World! 该页面已被访问 {} 次。\n'.format(count)
if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
--------------------------------------------compose-docker.yml---------------------------------
# 模板文件
version: '3'
services:
# web相关配置
web:
build: .
# 模板文件与dockerfile在同一目录下
ports:
- "5000:5000"
redis:
image: "redis:alpine"
----------------------------------------自动化部署 项目------------------
docker compose up
##########################################################################
root@lss-virtual-machine:/opt# mkdir code
root@lss-virtual-machine:/opt# cd code/
root@lss-virtual-machine:/opt/code# ls
root@lss-virtual-machine:/opt/code# vi app.py
root@lss-virtual-machine:/opt/code# ls
app.py
root@lss-virtual-machine:/opt/code# vi Dockerfile
root@lss-virtual-machine:/opt/code# ls
app.py Dockerfile
root@lss-virtual-machine:/opt/code# vi docker-compose.yml
root@lss-virtual-machine:/opt/code# ls
app.py docker-compose.yml Dockerfile
root@lss-virtual-machine:/opt/code# docker compose up

浙公网安备 33010602011771号