添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  1. 1. 1. 为什么有很多<none>:</none>镜像,有的删除不掉,有些却删除不掉?
  2. 2. 如何删除已退出的容器的镜像?
  3. 3. 如何查看容器完整ID?
  4. 4. 如何查看容器运行的命令?
  5. 5. docker stack不支持加载.env文件,怎么解决?
  6. 6. 生成环境怎么使用docker部署nodejs应用?
  7. 7. docker swarm模式下使用traefik做负载均衡时候无法获取到客户端IP?
  8. 8. docker swarm模式下一个容器有多个端口,使用traefik做复制该如何配置?
  9. 9. 当我们构建nodejs应用镜像,全局安装某依赖时候,有时候出现权限拒绝该怎么解决?
  10. 10. docker部署mysql时候,日志目录不可写问题?
  11. 11. docker部署grafana数据目录权限导致问题
  12. 12. docker容器内外相互拷贝数据

下面是我在使用docker过程中遇到的一些问题以及解答,现记录下来备查。

1. 为什么有很多 <none>:</none> 镜像,有的删除不掉,有些却删除不掉?

我们执行命令 docker images -a 有时候会发现不少 : 镜像,使用 docker rmi image_name 删除这些none镜像时候,有时候能够成功,有时候却不能成功。这究竟为什么?

我们知道镜像是分层的,上面一层依赖下一层,下一层是上一次的父镜像层。就像下面这样:

我们可以通过 docker inspect 查看镜像ID 和父层镜像ID

上图中镜像ip-scout的ID是 28ee11309524 ,它的父镜像层ID是 a8e836f776fa , 接着我们看看上图父镜像层信息:

我们发现ip-scout镜像的父镜像层就是 : ,这就是一部分 : 镜像的来源–在 docker build docker pull 过程中产生的中间层镜像,这些none镜像是无法删除的。最上层镜像由于我们命名了所以不再是你none,就好比 28ee11309524 的名称就是 ip-scout:latest

我们可以通过 docker history 查看所有层:

: 另一个来源是悬空镜像(dangling),这种一般发生在build或者pull过程。其中一个情况就是重新构建镜像时候,如果依赖的父镜像已经更新了,我们新构建的新镜像指向了新的父镜像,而我们之前构建的镜像指向的还是旧的父镜像,那么之前镜像就变成 untagged dangling ,这类镜像占用空间,可以使用下面命令进行删除的:

1
docker rmi $(docker images -f "dangling=true" -q)

如何删除已退出的容器的镜像?

我们可以使用下面命令

1
2
docker stop $(docker ps -a | grep "Exited" | awk '{print $1 }')
docker rm $(docker ps -a | grep "Exited" | awk '{print $1 }')

如何查看容器完整ID?

我们使用docker ps命令查看到的容器ID是短ID,我们可以使用以下命令查看完整ID:

1
docker inspect --format="{{.Id}}" container_name

如何查看容器运行的命令?

有时候我们忘记当时是怎么运行容器的,可以通过以下命令查看:

1
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock  assaflavie/runlike container_id

docker stack不支持加载.env文件,怎么解决?

docker compose 支持.env文件来设置环境变量,但是docker swarm集群部署模式下不支持.env环境,有时候我们确实很需要,可以这样:

1
export $(cat .env) && docker stack deploy -c docker-stack.yml web

生成环境怎么使用docker部署nodejs应用?

生产推荐使用 pm2 部署nodejs应用,支持自动重启,集群部署。

下面是构建nodejs应用镜像Dockerfile

1
2
3
4
5
6
7
FROM node
WORKDIR /app
COPY . /app
RUN npm install pm2 -g
RUN npm install --only=production
EXPOSE 8989
CMD ["pm2-runtime", "/app/server.js", "--name", "your-app-name"]

后续步骤略

docker swarm模式下使用traefik做负载均衡时候无法获取到客户端IP?

问题原因是docker swarm模式本身问题 moby/moby#25526

通过配置traefik服务对外暴露端口可以解决此问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
traefik:
image: traefik
ports:
- target: 80
published: 80
protocol: tcp
mode: host
- target: 443
published: 443
protocol: tcp
mode: host
- target: 8080
published: 8080
protocol: tcp
mode: host

docker swarm模式下一个容器有多个端口,使用traefik做复制该如何配置?

我们可以配置traefik的段标签(segment labels)来解决此问题,格式如下:

1
2
3
4
traefik.<segment_name>.backend=BACKEND
traefik.<segment_name>.port=PORT
traefik.<segment_name>.domain=DOMAIN
traefik.<segment_name>.frontend.auth.basic=EXPR

更多查看 traefik On containers with Multiple Ports (segment labels)

当我们构建nodejs应用镜像,全局安装某依赖时候,有时候出现权限拒绝该怎么解决?

我们一般使用官方镜像作为父镜像构建我们应用的镜像,有时候在运行 npm install xxx -g 命令时候会提示类似如下的权限问题:

1
{ Error: EACCES: permission denied xxxx }

这是由于镜像默认用户是root,我们全局安装某些依赖时候,限制使用root安装。这时候可以更改镜像用户和依赖安装目录:

1
2
3
4
USER node
RUN mkdir /home/node/.npm-global && mkdir /home/node/app
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
ENV PATH=$PATH:/home/node/.npm-global/bin

docker部署mysql时候,日志目录不可写问题?

使用docker-compose进行编排:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# docker-compose.yml
version: '3.3'

services:
mysql-master:
image: mysql:5.7
container_name: mysql-master
restart: always
ports:
- "3306:3306"
environment:
- "MYSQL_ROOT_PASSWORD=123456"
volumes:
- /opt/mysql-master-slave/data/master:/var/lib/mysql # data目录
- /opt/mysql-master-slave/log/master:/var/log/mysql # 日志目录
- /opt/mysql-master-slave/mysqld-master.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf # 配置

容器启动时候,提示日志目录写入失败:

1
sudo chown 999:999 /opt/mysql-master-slave/log/master

docker部署grafana数据目录权限导致问题

部署grafana时候由于挂载的数据目录权限问题会导致:

1
2
3
GF_PATHS_DATA='/var/lib/grafana' is not writable.
You may have issues with file permissions, more information here: http://docs.grafana.org/installation/docker/#migration-from-a-previous-version-of-the-docker-container-to-5-1-or-later
mkdir: cannot create directory '/var/lib/grafana/plugins': Permission denied

docker-composer.yml文件:

1
2
3
4
5
6
7
8
9
grafana:
image: grafana/grafana
ports:
- "127.0.0.1:3100:3000"
environment:
- "GF_SERVER_ROOT_URL=%(protocol)s://%(domain)s:%(http_port)s/grafana"
- GF_SECURITY_ADMIN_PASSWORD=123456
volumes:
- $PWD/data/grafana:/var/lib/grafana

解决办法:更改挂载目录的用户和组

1
sudo chown -R 472:472 $PWD/data/grafana

docker容器内外相互拷贝数据

从宿主机上拷贝文件或目录到容器内:

1
2
docker cp 文件 容器名:目录
docker cp 目录 容器名:目录

从容器内拷贝文件或目录到宿主机上:

1
2
docker cp 容器名:文件 目录
docker cp 容器名:目录 目录

附: Nodejs应用dockerize最佳时间

12-factor 2FA API API网关 Ansible Awk CA CSRF Cheat Sheet Consul Coredns Data Science Debounce Devops Docker Elasiticsearch小技巧 Elasticsearch优化 Elasticsearch内存占用 GDB GMP模型 Golang Go通道 HTTP HTTP Cache HTTP协议 HTTP状态码 JAVASCRIPT Jupyter notebook Linux命令 Linux命令大全 Linux配置 Logrotate Lua Nginx Opcache PHP PHP-FPM PHP优化 Pandas Prometheus QPS RESTful Redis Redis主从复制 Redis系统服务 SQL注入 SSH SSL SSL证书 Systemd TLS Throttle Webgrind Web安全 Wireshark XSS Xdebug context docker golang golang defer grpc iptables k8s nat netstat nil通道 protobuf pyspark python spark sublime sublime插件 tmux tow-factor authentication 东西流量 人生 代理 代码模式 代码质量 供给侧 函数选项 分布式 分布式ID 分析 南北流量 原创翻译 原子操作 双因素认证 反射 反射三定律 取模运算 吞吐量 固件 完全指南 嵌入式编程 年度回顾 并发数 并发编程 微控制器 微服务 性能优化 性能优化工具 性能指标 技术分享 持续集成 持续集成工具 效率神器 数学证明 日志管理 时区 易错点 服务发现 服务网格 格言 汇编 爱情 程序内存布局 算法 终端复用 统计学 统计思维 翻译 自动化部署 自旋锁 营改增 设计模式 调试工具 软件架构 通道 配置中心 配置管理 重构 错误与异常 问题汇总 阅读习惯