docker学习
1. 安装
官方地址一键安装: curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun 或国内 daocloud 一键安装: curl -sSL https://get.daocloud.io/docker | sh 拆解: curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh
手动安装(centos为例):
移除旧版本 yum remove docker \ docker-client \ docker-client-latest \ docker-common \ docker-latest \ docker-latest-logrotate \ docker-logrotate \ docker-engine 添加docker的yum源 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 装包(可通过其完整的软件包名称安装特定版本,例如:docker-ce-18.09.1,默认最新版) yum install docker-ce docker-ce-cli containerd.io 启服务 systemctl start docker 卸载 yum remove docker-ce 删除镜像,容器,配置文件等残留 rm -rf /var/lib/docker
测试
docker run hello-world
下载镜像
docker pull 镜像名
常见报错:”Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get http://%2Fvar%2Frun%2Fdocker.sock/v1.26/images/json: dial unix /var/run/docker.sock: connect: permission denied“
原因分析:使用非root用户运行docker。docker进程使用Unix Socket而不是TCP端口;而默认情况下,Unix socket属于root用户,需要root权限才能访问。
解决方法1
给当前用户配置sudo权限,使用sudo获取管理员权限,运行docker命令。
解决方法2
docker守护进程启动的时候,会默认赋予名字为docker的用户组读写Unix socket的权限,因此只要创建docker用户组,并将当前用户加入到docker用户组中,那么当前用户就有权限访问Unix socket了,进而也就可以执行docker相关命令
sudo groupadd docker #添加docker用户组
sudo gpasswd -a $USER docker #将登陆用户加入到docker用户组中
newgrp docker #更新用户组
docker ps #测试docker命令是否可以使用sudo正常使用
2. 常用命令
2.1 启容器 直接启容器 docker run 例: docker run ubuntu:15.10 /bin/echo "Hello world" 输出:hello world 交互式登陆容器内部 -t: 在新容器内指定一个伪终端或终端。 -i: 允许你对容器内的标准输入 (STDIN) 进行交互。
--name: 创建容器时,指定容器名
/bin/bash:放在镜像名后的是命令,这里我们希望有个交互式 Shell,因此用的是 /bin/bash 使用exit退出伪终端 docker run -i -t 例: docker run -it --name test ubuntu:15.10 /bin/bash root@0123ce188bd8:/#exit 后台模式 -d:将容器进程挂在系统后台运行 docker run -d 例: docker run -d ubuntu:15.10 /bin/sh -c "while true; do echo hello world; sleep 1; done" 前台输出:容器ID 此时查看后台输出:docker logs 容器名/ID 停止容器 docker stop 容器名/ID
运行已停止的容器
docker start 容器名/ID
重启正在运行的容器
docker restart 容器名/ID
进入容器
-
docker attach 容器名/ID:如果从这个容器退出,会导致容器的停止。
-
docker exec -it 容器名/ID /bin/bash:推荐大家使用 docker exec 命令,因为此命令会退出容器终端,但不会导致容器的停止。
web容器运行示例:
在docker容器中运行一个 Python Flask 应用来运行一个web应用。
启服务
docker pull training/webapp # 载入镜像
docker run -d -p 10.10.1.10:8080:5000 training/webapp python app.py --name webapp01
-
-d:让容器在后台运行。
-
-P:不加参数,会直接将容器内部暴露的网络端口全部随机映射到我们使用的主机上。
- -P 5000:将5000端口映射到主机上,未指定主机端口,则随即映射到一个端口上,未指定IP,则为0.0.0.0。
- -p 8080:5000:将容器5000端口映射到主机8080端口(绑定主机8080端口和容器的5000端口)。
- -p 10.10.1.10:8080:5000:将容器IP10.10.1.10和端口5000映射到主机8080端口上。
- -P 10.10.1.10::5000:将容器IP10.10.1.10和端口5000随机映射到主机端口上。
- 多端口映射时,只需要多几个-p选项即可。
- 大写P不指定端口,小写p指定端口。
查看
# docker ps CONTAINER ID IMAGE COMMAND ... PORTS d3d5e39ed9d3 training/webapp "python app.py" ... 10.10.1.10:8080->5000/tcp
# docker port webapp01
5000/tcp->10.10.1.10:8080
Docker 开放了 5000 端口(默认 Python Flask 端口)映射到主机端口 8080上。即外部访问端口为8080。
停止
docker stop webapp01
移除
docker rm webapp01
注:移除容器需要先停止容器,然后再移除,否则会报错。
2.2 查看
查看正在运行的容器 docker ps
查看所有容器
docker ps -a
查看最后一次,创建的容器
docker ps -l
输出详情介绍: CONTAINER ID: 容器 ID。 IMAGE: 使用的镜像。 COMMAND: 启动容器时运行的命令。 CREATED: 容器的创建时间。 STATUS: 容器状态。 状态有7种: created(已创建) restarting(重启中) running 或 Up(运行中) removing(迁移中) paused(暂停) exited(停止) dead(死亡) PORTS: 容器的端口信息和使用的连接类型(tcp\udp)。 NAMES: 自动分配的容器名称。
2.3 镜像
查找镜像(先本地仓库查找,再网络仓库查找)
docker search 镜像名(关键词)
查看本地镜像
docker images 下载镜像 docker pull 镜像名/ID
上传镜像
docker push 镜像名/ID
删除镜像
docker rmi 镜像名/ID
导出/入镜像
从本地镜像种导出镜像文件,可保留所有镜像层,导入时无法直接重命名容器和标签
docker save -o webapp01.tar webapp:v1 hello-world 导出两个镜像
docker load < webapp01.tar 导入
或
从容器中导出,无法同时打包多个镜像,无法保留历史镜像标签,导入时可重新定义容器名和标签
docker export -o webapp02.tar webapp02
docker import webapp02.tar webapp02:v1
或
docker export webapp02 > webapp02.tar
docker import webapp02:v1 < webapp02.tar
创建/更新镜像
docker commit -m="only for test v1" -a="santiagod" e321bcd0987 santiagod/webapp01:v1
-
-m: 提交的描述信息
-
-a: 指定镜像作者
-
e321bcd0987:容器名/ID
-
santiagod/webapp01: 指定要创建的目标镜像名
- :v1: tag标签v1
修改镜像名和标签
先查看镜像ID
docker images
再修改镜像名(只改标签则镜像名不变,只改镜像名则不写标签或者标签不变)
docker tag 镜像名/ID 新镜像名:新标签
最后删除原来的镜像
docker rmi 镜像名/ID
官网镜像仓库:https://hub.docker.com
docker login 登陆
docker logout 登出
私有仓库搭建
registry仓库
yum -y install docker-registry
或
docker image pull registry
可以通过获取官方registry镜像来运行。默认情况下,仓库会被创建在容器的/var/lib/registry目录下。可以通过-v参数来将镜像文件存放在本地的指定路径。
docker run --name registry -d -p 5000:5000 --restart=always -v /opt/data/registry:/var/lib/registry registry
设置仓库IP:
对于使用systemd的系统,请在/etc/docker/daemon.json中写入如下内容(如果文件不存在请新建该文件)
{
"registry-mirror":[
"http://hub-mirror.c.163.com"
],
"insecure-registries":[
"10.10.1.10:5000"
]
}
使用示例:
docker push 10.10.1.10:5000/session-web:latest
haber仓库
wget https://storage.googleapis.com/harbor-releases/release-1.9.0/harbor-online-installer-v1.9.0.tgz
tar xvf harbor-online-installer-v1.9.0.tgz
vim /harbor/harbor.yml
hostname IP或域名皆可
port 通信端口
./install.sh
web访问http:/IP/域名:端口
,账号默认为:admin,密码:Harbor12345,新建项目
由于docker的版本从13开始,register只能用https,由于我们配的都是http的,所以要先在/etc/docker/
目录创建daemon.json
文件并加入如下
{ "insecure-registries":["xxx:5000"] }
重启docker
systemctl restart docker
重启harbor相关的容器,因为重启docker后这些都关闭了,所以我们通过docker ps -a
找到所有与harbor相关的镜像,通过docker restart xx xx xx
对应容器名重启即可
正式提交镜像
# 先登录
docker login xxx:5000
# 打标签
docker tag maven xxx:5000/guojing/maven:latest
# 提交
docker push xxx:5000/guojing/maven:latest
修改端口 1. 可以先将当前容器,提交镜像,然后重启时修改端口。 docker ps 查容器名/id docker commit 提交新镜像 docker run -p 修改端口,启用新容器 docker stop 停止旧容器 docker rm 删除旧容器容器
docker rename 新容器名 旧容器名
理论上可以无缝衔接,但需要考虑的是,容器ID变了,是否会造成其他影响
2. 修改j容器son文件 注:只重启容器配置修改不会生效,需要先停止docker服务,但相应的容器也随之停止(podman好像不会有这个问题)。 systemctl stop docker 配置文件路径/var/lib/docker/containers/容器ID 先修改hostconfig.json; 如果之前没有端口映射, 应该有这样的一段: “PortBindings”:{} 增加一个映射, 这样写: “PortBindings”:{“8080/tcp”:[{“HostIp”:””,“HostPort”:“60000”}]} 前一个数字是容器端口, 后一个是宿主机端口。将宿主机的60000端口映射到容器的8080端口 而修改现有端口映射更简单, 把此处的端口号改掉就行。 sed -i 's/8081/8008/' /var/lib/docker/containers/7d378d1ff205b9a1d08eb91b881e9c1b2fe81f10bfc2c56abd759d20b9ea63b9/hostconfig.json
如果有config.v2.json文件,需要视情况修改,以下IP都是容器内部IP
"ExposedPorts":{ "80/tcp":{ }}
当然如果添加多端口映射,可参考以下内容
hostconfig.json
“PortBindings”:{“80/tcp”:[{“HostIp”:””,“HostPort”:“8080”}],“3306/tcp”:[{“HostIp”:””,“HostPort”:“33060”}],“XXX/tcp”:[{“HostIp”:””,“HostPort”:“xxx”}]}
config.v2.json
"ExposedPorts":{ "80/tcp":{ },"3306/tcp":{ },"XXXX/tcp":{ }}
然后启docker
systemctl restart docker
接着启容器
docker start 7d378d1ff205b
dockerfile
FROM:定制的镜像都是基于 FROM 的镜像,这里的 nginx 就是定制需要的基础镜像。后续的操作都是基于 nginx。
RUN:用于执行后面跟着的命令行命令。
COPY: 复制指令,从上下文目录中复制文件或者目录到容器里指定路径。<目标路径>:容器内的指定路径,该路径不用事先建好,路径不存在的话,会自动创建。
ADD 指令和 COPY 的使用格类似(同样需求下,官方推荐使用 COPY)。功能也类似,不同之处如下:
- ADD 的优点:在执行 <源文件> 为 tar 压缩文件的话,压缩格式为 gzip, bzip2 以及 xz 的情况下,会自动复制并解压到 <目标路径>。
- ADD 的缺点:在不解压的前提下,无法复制 tar 压缩文件。会令镜像构建缓存失效,从而可能会令镜像构建变得比较缓慢。具体是否使用,可以根据是否需要自动解压来决定。
CMD: 类似于 RUN 指令,用于运行程序,但二者运行的时间点不同:
- CMD 在docker run 时运行。只能一个。
- RUN 是在 docker build。可以有多个。
作用:为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束。CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。
注意:如果 Dockerfile 中如果存在多个 CMD 指令,仅最后一个生效。
ENTRYPOINT:类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序。
但是, 如果运行 docker run 时使用了 --entrypoint 选项,将覆盖 ENTRYPOINT 指令指定的程序;可以搭配 CMD 命令使用:一般是变参才会使用 CMD ,这里的 CMD 等于是在给 ENTRYPOINT 传参
优点:在执行 docker run 的时候可以指定 ENTRYPOINT 运行所需的参数。
注意:如果 Dockerfile 中如果存在多个 ENTRYPOINT 指令,仅最后一个生效。
假设已通过 Dockerfile 构建了 nginx:test 镜像: FROM nginx ENTRYPOINT ["nginx", "-c"] # 定参 CMD ["/etc/nginx/nginx.conf"] # 变参 1、不传参运行 $ docker run nginx:test 容器内会默认运行以下命令,启动主进程。 nginx -c /etc/nginx/nginx.conf 2、传参运行 $ docker run nginx:test -c /etc/nginx/new.conf 容器内会默认运行以下命令,启动主进程(/etc/nginx/new.conf:假设容器内已有此文件) nginx -c /etc/nginx/new.conf
ENV: 设置环境变量,定义了环境变量,那么在后续的指令中,就可以使用这个环境变量。
格式:
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
ARG: 构建参数,与 ENV 作用一致。不过作用域不一样。ARG 设置的环境变量仅对 Dockerfile 内有效,也就是说只有 docker build 的过程中有效,构建好的镜像内不存在此环境变量。
构建命令 docker build 中可以用 --build-arg <参数名>=<值> 来覆盖。
VOLUME: 定义匿名数据卷。在启动容器时忘记挂载数据卷,会自动挂载到匿名卷。
作用:
- 避免重要的数据,因容器重启而丢失,这是非常致命的。
- 避免容器不断变大。
格式:
VOLUME ["<路径1>", "<路径2>"...]
VOLUME <路径>
在启动容器 docker run 的时候,我们可以通过 -v 参数修改挂载点。
EPOSE:仅仅只是声明端口。
作用:
- 帮助镜像使用者理解这个镜像服务的守护端口,以方便配置映射。
- 在运行时使用随机端口映射时,也就是 docker run -P 时,会自动随机映射 EXPOSE 的端口。
格式:
EXPOSE <端口1> [<端口2>...]
WORKDIR:指定工作目录。用 WORKDIR 指定的工作目录,会在构建镜像的每一层中都存在。(WORKDIR 指定的工作目录,必须是提前创建好的)。
docker build 构建镜像过程中的,每一个 RUN 命令都是新建的一层。只有通过 WORKDIR 创建的目录才会一直存在。
USER: 用于指定执行后续命令的用户和用户组,这边只是切换后续命令执行的用户(用户和用户组必须提前已经存在)。
格式:
USER <用户名>[:<用户组>]
HEATHCHECK: 用于指定某个程序或者指令来监控 docker 容器服务的运行状态。
格式:
HEALTHCHECK [选项] CMD <命令>:设置检查容器健康状况的命令
HEALTHCHECK NONE:如果基础镜像有健康检查指令,使用这行可以屏蔽掉其健康检查指令
HEALTHCHECK [选项] CMD <命令> : 这边 CMD 后面跟随的命令使用,可以参考 CMD 的用法。
ONBUILD: 用于延迟构建命令的执行。简单的说,就是 Dockerfile 里用 ONBUILD 指定的命令,在本次构建镜像的过程中不会执行(假设镜像为 test-build)。当有新的 Dockerfile 使用了之前构建的镜像 FROM test-build ,这时执行新镜像的 Dockerfile 构建时候,会执行 test-build 的 Dockerfile 里的 ONBUILD 指定的命令。
格式:
ONBUILD <其它指令>
LABEL: 用来给镜像添加一些元数据(metadata),以键值对的形式,语法格式如下:
LABEL <key>=<value> <key>=<value> <key>=<value> ...
比如我们可以添加镜像的作者:
LABEL org.opencontainers.image.authors="santiagod"
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)