这篇文章记录几个 docker compose 使用过程中几个难以察觉的错误使用姿势

1. 变量值使用@符号开头

我在 RSS MAN X 的 docker-compose 配置文件中,huignn 的环境变量出来时是这样写的

environment:
	- DATABASE_ADAPTER=postgresql
	- DATABASE_HOST=database.huginn
	- DATABASE_USERNAME=postgres
	- DATABASE_PASSWORD=@pass_for_DB
	- DATABASE_PORT=5432

自己使用的时候没发现什么问题,别人从零创建容器的时候报错了。刚开始排查了很久,后面发现我默认密码这样写其实是有问题的。

上面的使用列表来描述环境变量在 docker-compose 解析的时候没有任何报错信息。但是使用下面这种 key-value 的 map 的形式时,docker-compose up命令报错了,说 YAML 解析时出现问题

environment:
	DATABASE_ADAPTER: postgresql
	DATABASE_HOST: database.huginn
	DATABASE_USERNAME: postgres
	DATABASE_PASSWORD: @pass_for_DB
	DATABASE_PORT: 5432
yaml: line 17: found character that cannot start any token

删除前导@符号则一切正常了。

DATABASE_PASSWORD: pass_for_DB

后续测试了几次到底是什么原因导致的

# error
DATABASE_PASSWORD: @pass_for_DB	

# correct
DATABASE_PASSWORD: pass_for_DB

# correct
DATABASE_PASSWORD: ${DB_Password:-'pass_for_DB'}
## in .env
DB_Password=www_123

# correct
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## in .env
DB_Password=www_123

# error
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## no .env

# error
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## in .env
DB_Password=@www_123

# correct
DATABASE_PASSWORD: ${DB_Password:-'@pass_for_DB'}
## in .env
DB_Password=A@www_123

最终发现无论是否使用 docker-compose 变量替换,只要最终设定值的时候,包含前导@符号,最终一定会失败。Huginn 的这边的报错为解析容器内的一个 YAML 文件时失败

huginn1     | foreman stderr | 
huginn1     | Caused by:
huginn1     | foreman stderr | Psych::SyntaxError: (<unknown>): found character that cannot start any token while scanning for the next token at line 8 column 13
huginn1     | foreman stderr | /app/vendor/bundle/ruby/2.6.0/gems/railties-6.0.4.4/lib/rails/application/configuration.rb:232:in `database_configuration'

后面我又进入容器查看了下容器内部读取到的环境变量到底是不是预期的值,发现了问题所在

能正常使用的情况

~ » sudo docker exec -it huginn1 /bin/bash
default@3b652a8413fb:~$ echo $DATABASE_HOST
database.huginn
default@3b652a8413fb:~$ echo $DATABASE_PASSWORD
A@www_123

出错的情况

~ » sudo docker exec -it huginn1 /bin/bash
default@42e19e692b24:~$ echo $DATABASE_HOST
database.huginn
default@42e19e692b24:~$ echo $DATABASE_PASSWORD
'@pass_for_DB'

可以看到,如果以@符号开头,最终的环境变量会加上引号,这对于某些应用来说会产生预期之外的结果,如此处测试的 Huginn。

2. 使用 6000 或 6666 端口

这也是一定挺特殊的场景,虽然与 docker compose 关系不大,但是难免会遇到。在映射端口的时候有一个很坑的地方,如果你要部署一个 web 服务,然后映射的时候填写的是6000端口或者是6666端口,你会发现无论怎么重启容器、更改容器设置、更换 Edge/Chrome,浏览器就是访问不了页面。

实在折腾地快疯了,点开 Chrome 的错误详情,才发现这么一句

ERR_UNSAFE_PORT

一查才发现,Chrome 等浏览器会限制部分特殊端口的网页访问,这些端口一般都已经有特殊的作用。

https://www.jianshu.com/p/40f79f584eae

这里列出 1000 以上的部分会有相关问题的端口,别的不说,感觉60006666还是很容易一不小心就会设置的端口。。。。

  2049, // nfs
  3659, // apple-sasl / PasswordServer
  4045, // lockd
  6000, // X11
  6665, // Alternate IRC
  6666, // Alternate IRC
  6667, // Standard IRC
  6668, // Alternate IRC
  6669, // Alternate IRC

Chrome、FireFox 等都会有类似的行为,换多少浏览器、换多少版本可能也都不行。。。

根据网友描述,部分特殊情况下,其他可能会被拦截的端口也包括8080844310080

总之,日常映射端口还是选取10000以上的高位端口吧,避免不必要的麻烦:)