- Published on
Docker 备忘
# 启动 docker 服务
sudo service docker start
# 交互方式启动
docker run -it ubuntu bash
# 后台服务模式启动
docker run -d ubuntu bash -c "while true; do echo hello world;
sleep 1; done"
# 映射端口和数据卷
docker run --name mongo --port 2234:80 -v /tmp/data:/data/db
# 进入处于后台模式的容器
docker exec -it [container id] /bin/bash
# 查看某个命令的用法
docker --help
docker [command] --help
# 查看输出
docker logs containerid
# 删除容器
docker rm -f containerid
# 查看容器的端口信息
docker port containerid
# 查看容器网络信息
docker network inspect bridge
国内镜像源
使用 docker 国内的官方源 https://registry.docker-cn.com
或者是网易的镜像源http://hub-mirror.c.163.com
网易的源会快一点。
cd ~/.docker
vim daemon.json
{
"experimental" : false,
"debug" : true,
"registry-mirrors": ["https://registry.docker-cn.com"]
}
Docker run
设置环境变量
docker run -e NODE_ENV=prod node index.js
docker run --env-file .env node index.js
重启
docker run --restart=on-failure node index.js
docker commit
如果一个容器内的文件有改动需要生成新的镜像就可以使用 docker commit
。
# 为 ubuntu 镜像添加 curl 工具
docker run -it ubuntu bash
# 在容器内
apt-get update
apt install net-tools
aput install curl
# 在宿主机的终端提交
docker commit [container id] ubuntu_nettools_curl
docker 限制容器的 cpu 和内存
tag 概念
多阶段构建
什么情况下会生成中间镜像
容器网络连接
none 模式
容器没有网卡,ip,路由等信息,需要自行配置。这种方式网络隔离最彻底。
host 模式
docker 容器使用宿主机的 ip 和端口,但是文件系统还是隔离的,最大好处就是性能。
docker run --network host nginx
docker run --network host ubuntu
# 在 ubuntu 容器里面可以这样访问 nginx
curl http://localhost:80
注意:mac 版本的 docker host 模式有点不一样,以上在 ubuntu docker 测试通过。
bridge 模式
docker 启动后创建一个虚拟网桥 docker0,宿主机和容器都连接到这个网桥上面,并且都分配了处于该子网段的 ip,通过这种方式,不同容器之间,容器和宿主机器之间可以通过子网段 ip 地址互联。docker 默认为桥接模式,可以将容器和宿主机都想象成连接到同一网关的不同机器。
docker 默认的网络模式就是 bridge 模式。虽然它比 host 模式更复杂,但是也更安全。

如下图,在 ubuntu 中,宿主机有两个不同的网卡,eth0 是主机内网 ip 地址,而主机在 docker0 网桥上的地址是 172.17.0.1。

容器内的 IP:

由此可知他们在同一网段下。
在开发调试的时候,bridge 模式的容器要访问宿主机的 ip,还可以通过 host.docker.internal 这个指定的 DNS 名称来访问。
通过自定义 bridge 模式实现容器互联
虽然在 bridge 模式下容器之间可以通过子网段的 ip 地址互联,但是无法保证 docker 每次启动后都是 docker0 的网段都是一样的。所以需要一种别名的方式来代替各容器的 ip 地址。
针对外界网络,自定义 bridge 模式提供了更好的隔离型,而针对同一 bridge 下的容器,则有更好的互通性。
具体步骤如下:
- 创建自定义 bridge
docker network create -d bridge my-net
- 将容器连接到该 bridge
docker network connect my-net nginx_demo
docker network connect my-net ubuntu_demo
- 进入容器检查互通性
docker exec -it ubuntu_demo bash
# 可以通过容器名称访问容器
curl http://nginx_demo
- 断开和默认网桥的连接
docker network disconnect bridge nginx_demo
docker network disconnect bridge ubuntu_demo
Dockerfile
docker build
docker build [options] PATH | URL
docker build 需要 Dockerfile 和 context 。 context 可以是本地文件路径或者是一个 git 仓库的地址。构建的时候会将整个 context 的内容上传到 docker daemon。删除不必要的文件可以加快构建过程。
# 默认 Dockfile 的位置为 context 的第一级目录
# 指定 Dockerfile 的位置和 context 为当前路径
docker build -f /path/Dockfile .
docker 会在构建的时候使用中间镜像来加速构建。
格式
- 行首为 # 的都视为注释
- 可以在 FROM 指令前面的,只有 parser directives, comments, 和 global args.
- 使用 \ 作为行连接符
- 指令建议都用大写
parser directives
编译指定以键值对注释的形式放在 Dockerfile 文件的最顶层。不是放在最顶层的 parser directives 都视为普通注释。目前支持的 parser directives 有:
- syntax: 指定 Dockerfiel builder 的位置。
# syntax=docker/dockerfile
# syntax=docker/dockerfile:1.0
# syntax=docker.io/docker/dockerfile:1
# syntax=docker/dockerfile:1.0.0-experimental
# syntax=example.com/user/repo:tag@sha256:abcdef...
这个只有在启用 Buildkit 的时候才会起作用,如果不想使用 Docker build 新的特性的话,保持默认不指定就好。
escape
# escape=\
指定 Dockerfile 的行连接符, 默认是反斜杠。
ENV 指令
ENV key value
ENV key=value
ENV mycat Jonhn jeffy
# 等价于
ENV mycat=John\ jeffy
在 Dockerfile 文件中可以用 variablename 的形式引用。
FROM busybox
ENV foo /bar
WORKDIR ${foo} # WORKDIR /bar
ADD . $foo # ADD . /bar
COPY \$foo /quux # COPY $foo /quux
ENV 指定设置的环境变量会一直存在于镜像中 。这个可能会造成一些影响。在单个指令中指定环境变量,可以这样做:
RUN key=value command
.dockerignore
dockerignore 文件允许你指定包含或者忽略哪些文件参与构建。忽略的文件将不会发送到 docker daemon。
# 忽略所有 md 文件
*.md
# 但是允许 readme md
!readme*.md
# /somedir/temporary.txt
*/temp*
# /somedir/subdir/temporary.txt
*/*/temp*
# ** 表示任意层级的文件夹
# /temp
# /dir/temp
**temp
ARG
在 Dockfile 的顶部设置变量以供后面的命令使用
ARG VERSION=latest
FROM node:${VERSION}
FROM
FROM 指令指定镜像的基础镜像。
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
- 多阶段构建的时候一个 Dockerfile 文件里面有多个 FROM 指令。
- Tag 是可选的,如果不指定,默认是 latest
- name 用于多阶段构建时 COPY 指令
COPY --from=<name|index>
RUN
两种形式
RUN command paramer1
# 必须使用双引号
RUN ["command", "paramer1"]
RUN 命令默认会生成 cache,也就是中间镜像,以供下次构建,可以通过命令指定不生成 cache。
docker build --no-cache .
CMD
CMD 有三种形式
CMD ["executable","param1","param2"]
(exec form, this is the preferred form)CMD ["param1","param2"]
(as default parameters to ENTRYPOINT)CMD command param1 param2
(shell form)
CMD ["sh", "-c", "/usr/start.sh", "--someflag"]
# 等价于
CMD sh -c /usr/start.sh --someflag
如果数组中的第一个元素不是可执行,则是第二种形式,作为 ENTRYPOINT 的参数,
会被 docker run 和 ENTRYPOINT 覆盖。
ENTRYPOINT
ENTRYPOINT 有两种形式
# exec form
ENTRYPOINT ["executable", "param1", "param2"]
# shell form
ENTRYPOINT command param1 param2
CMD 和 ENTRYPOINT 都可作为启动容器时默认的执行命令,他们的相互作用如下表
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] | |
---|---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry exec_cmd p1_cmd |
CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry p1_cmd p2_cmd |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry | exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd |
容器的启动命令,Dockerfile 中可以有多条 ENTRYPOINT,但只有最后一条生效。
CMD 和 docker run 之后的参数会当作参数传给 ENTRYPOINT。
LABEL
指定镜像的标签
LABEL author=jelee
# 使用 docker inspect 查看镜像标签
docker image inspect --format="" myimage
{
"author": "jelee"
}
EXPOSE
EXPOSE <port1> [<port2>/<protocol>...]
EXPOSE 80 80/tcp
声明容器要监听的宿主机端口 port1 要转发的 容器内端口 port2,同时指定端口协议为 tcp。
可以通过 docker run -p 8888:80/tcp
命令覆盖。
ADD COPY
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
# 添加所有 hom 开头的文件
ADD hom* /mydir/
# ? 表示单个字符
ADD hom?.txt /mydir/
这两个命令都是用来将 src (可是是 url 或者是文件,文件夹)复制到镜像 dest中。区别:
- COPY 只复制 src 文件夹中的内容,不包括自身文件夹
- COPY 可指定
--from=<name|index>
从中间镜像中复制内容 - 在 ADD 中,如果src 是 tar,zip,tgx, xz 等归档文件,将会自动解压
相关错误
- docker 映射端口报错
driver failed programming external connectivity on endpoint nervous_villani
解决办法: 重启docker
systemctl restart docker
- 打包镜像的时候安装 yarn,执行失败
解决办法是 :
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
RUN $HOME/.yarn/bin/yarn install