常用命令
以下说的 container
,即 container_name
或者 container_id
都可以。containers
即可以是多个容器。
# 查看 docker 状态
docker info
# 容器相关
# 不加 -a 参数只能看到正在运行的容器
docker container ls -a / docker ps -a(效果一样)
# 通过容器名,或者 ID ,启动/重启/停止/删除容器
docker container {start/restart/stop/rm} container_name[or container_id]
docker rm $(docker ps -a -q) # 删除所有容器
# 查看容器内的进程
docker top container_id
# 在容器外,向容器内发出命令。交互式运行
docker exec -it container_id /bin/bash(container_id 之后直接跟命令)
# 将容器中的文件复制到本地
docker container cp container_id:/path /host-path
# 镜像相关
# 查看所有的镜像,不加 -a 只能看到可用的镜像
docker images -a
# 拉取指定版本的镜像
docker pull ubuntu:12.04
# 查看构建镜像的历史信息
docker history image_id
# 删除镜像
docker rmi image_id
# 遇到相同 ImageId 的镜像,删除不想要的镜像仓库
docker image rm REPOSITORY:TAG
# 删除所有镜像
docker rmi $(docker images -q)
# 不常用的命令
# 查看多个容器的统计信息
docker stats containers
# 指定运行进程的所有者
docker exec -u root container
# 强制关闭容器
docker kill container
# 获取更详细的配置信息
docker inspect container
# 查看容器和主机的端口绑定关系
docker ps -l
docker port container container_port
# 登陆 docker hub
docker login
# 退出 docker hub
docker logout
run 命令
docker run --restart=always --name NewName -d -i -t -p 4000:80 --link db:db ubuntu:12.04 /bin/bash
命令解释:
参数 | 解释 |
---|---|
--name | 给容器指定一个名字 |
-i | 开启容器的 stdin,-i -t 一起使用,才能为容器提供一个交互式 shell |
-t | 为创建的容器分配一个伪 tty 终端 |
--restart=always | 由于某种错误而导致容器停止运行,通过这个参数可以自动重启容器 |
--restart=failure:5 | 只有当容器的推出代码为非0值是,才自动重启容器,重启次数为5次 |
-p 4000:80 | 将docker容器的80端口,映射到宿主机的4000端口上 |
--link db:db | 连接别的docker容器,参数是:<容器名称>:<别名>。 这种方式可以连接同一台主机上的不同docker容器。别名>容器名称> |
-d | 在后台运行一个守护式容器 |
--log-driver | 日志选项,默认是:json-file, 可以选择 --log-driver=”syslog”,将所有日志重定 向到系统日志。也可以选择none,仅用日志。 |
ubuntu:12.04 | 标签12.04是指镜像 ubuntu 的特定版本。 如果不加标签则下载 latest 标签的镜像 |
logs 命令
# 获取容器日志
docker logs container
# 监控日志
docker logs -f container
# 获取最后10条日志
docker logs --tail 10 container
# 跟踪最新的日志,而不必读取整个日志文件
docker logs --tail 0 -f container
# 给日志加上时间戳
docker logs -ft container
创建镜像命令与提交 docker hub
# 基于 Dockerfile 文件构建新镜像,并指定名字为 static_web
docker build -t="vincen666/static_web" .
# 如果构建失败,第二次构建时,忽略之前构建的缓存
docker build --no-cache -t="vincen666/static_web" .
docker login
# 给镜像打 tag
docker tag <image> username/repository:tag
# Upload tagged image to registry
docker push username/repository:tag
# Run image from a registry
docker run username/repository:tag
Dockerfile
格式
<指令> <参数> 参数>指令>
命令必须是大写。第一个命令一定是FROM。每一条命令都是独立运行的。命令是顺序执行的。
.dockerignore
Dockerfile 文件所在的目录即 docker 的“上下文”(context)。在这个目录中的所有文件都会传到 Docker 守护进程。可以使用 .dockerignore 文件来忽略不想要的目录和文件。文件的匹配模式见:go filepath Match。
指令
RUN, CMD, ENTRYPOINT 比较
RUN: 用于在 FROM 中设置的镜像上运行脚本或命令。RUN 运行结果会生成新的镜像,运行的详细信息记录到镜像历史中。
CMD: 用于设置容器启动时运行的脚本或命令。在 Dockerfile 只能设置一次,如果设置多个,只会执行最后一个。CMD 类似于 docker run
启动容器时的命令。
ENTRYPOINT: 用于设置容器启动时运行的脚本或命令。也只能设置一次。
CMD 版 Dockerfile
FROM ubuntu CMD [“echo”, “hello”]
运行时指定一个可执行命令:
sudo docker run container echo world
因为 docker run 设置的可执行命令会覆盖 CMD 指令,所以忽略 CMD 指令(不是因为 CMD 指令是 echo hello,其他的命令照样忽略),输出:world
ENTRYPOINT 版 Dockerfile:
FROM ubuntu ENTRYPOINT [“echo”, “hello”]
sudo docker run container echo world
虽然给 docker run 设置了可执行命令,但是并不会忽略 ENTRYPOINT 指令。而且,还会把设置的可执行命令作为参数,传递给 ENTRYPOINT。输出:hello echo world
若在 docker run 命令中设置了 --entrypoint 参数,则会忽略 Dockerfile 中的 ENTRYPOINT 指令。
ADD & COPY
ADD 指令添加本地压缩文件 hello.tar.gz,会解压缩,并将tar拆包。
但是添加网络文件时,只进行解压缩,不会将tar拆包。需要自己拆包。
COPY 不能添加网络文件,也不会进行解压缩和拆包这两个动作。
最佳实践
从容器内访问宿主机上的服务
If you are using Docker-for-mac or Docker-for-Windows 18.03+, just connect to your mysql service using the host host.docker.internal
(instead of the 127.0.0.1
in your connection string).
If you are using Docker-for-Linux 20.10.0+, you can also use the host host.docker.internal
if you started your Docker container with the --add-host host.docker.internal:host-gateway
option.
Otherwise, read below: https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach
修改容器内系统的时间
使用 docker 容器部署的应用,会出现时间与主机不一致的情况,是因为 Linux 系统默认是 GMT 的时区。中国时区是 GMT+8
将本机的 localtime
文件,拷贝到容器中的操作系统,然后重启即可解决。
cp /etc/localtime container_name:/etc/localtime
连接不同主机上的容器
使用ambassador容器,代理连接多台主机上的容器
数据卷容器
数据卷
使用如下命令将一个或多个容器的目录挂载到当前主机的目录上,在容器和主机间目录的内容都是共享的。
docker run -i -t -v /root/data:/data ubuntu /bin/bash
即把容器的/data目录挂载到当前主机的/root/data目录下。
Import: 不要期望 docker 把数据给你存到容器内部,实际上数据都是在主机的 /var/lib/docker/vfs/dir/xxxx 的目录下。当然如果你的主机是 Ubuntu 系统,docker 会使用 aufs 文件系统,那么目录就是:/var/lib/docker/aufs/diff/xxxx。由于没有名称,都是些类似以 uuid 为名字的目录,所以,数据还是放在数据卷中最好。
数据卷容器
数据卷容器就是个普通容器,其实就是提供了一个公共的地方映射数据。
容器A:/data ---->
数据卷容器:/data(数据卷) ----> /root/data
容器B:/data ---->
# 创建数据卷容器
docker run -i -t --name base-volume -v /root/data:/data ubuntu /bin/bash
# 创建容器A,并挂载到数据卷容器
docker run -d --volume-from base-volume --name containerA ubuntu
# 创建容器B,并挂载到数据卷容器
docker run -d --volume-from base-volume --name containerB ubuntu
alpine 镜像的特殊操作
# alpine 使用的是 ash shell
docker exec -it alpine /bin/ash
# 修改成阿里源
sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
# 更新源
apk update
# 安装 ssh
apk search openssh
apk add openssh
# 安装rc-service (类似于ubuntu的systemctl)
apk add openrc
# 设置 openrc,不加入这一行,open rc 无法正常工作
touch /run/openrc/softlevel
阿里镜像仓库
REPOSITORY | TAG | DESCRIPTION |
---|---|---|
ubuntu | v1 | BASE: ubuntu 20.04 阿里源 curl openssh-server |
jupyter | ||
node | v16 | npm@8.5.4 @angular/cli@13.2.6 typescript@4.6.2 |