Docker容器中FFmpeg推流YouTube时域名解析失败问题求助
问题描述
我正搭建一个Docker环境,使用NGINX RTMP服务器和PHP容器,通过HLS文件向YouTube Live推流。容器间通过共享卷传输文件,在PHP容器内使用FFmpeg启动推流时,遇到无法解析YouTube RTMP服务器域名的问题。
环境配置详情
Docker Compose配置(docker-compose.yml)
version: '2' services: rtmp: image: tiangolo/nginx-rtmp ports: - "1935:1935" volumes: - shared_data:/usr/share/nginx/hls - ./conf/nginx.conf:/etc/nginx/nginx.conf php: build: . ports: - "8080:80" volumes: - shared_data:/var/www/html/hls - ./src:/var/www/html security_opt: - seccomp:unconfined volumes: shared_data:
Dockerfile
FROM php:apache COPY --from=composer /usr/bin/composer /usr/bin/composer RUN curl -O https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz && \ tar -xJf ffmpeg-release-amd64-static.tar.xz && \ mv ffmpeg-*/ffmpeg /usr/local/bin/ && \ mv ffmpeg-*/ffprobe /usr/local/bin/ && \ rm -rf ffmpeg-*
./conf/nginx.conf
worker_processes auto; rtmp_auto_push on; events {} rtmp { server { listen 1935; listen [::]:1935 ipv6only=on; access_log /var/log/rtmp_access.log; chunk_size 4096; timeout 10s; application live { live on; record off; hls on; hls_path /usr/share/nginx/hls; hls_fragment 10s; } } }
NGINX容器接收来自GoPro相机的RTMP流,PHP容器提供推流管理UI并通过FFmpeg分发流,接收的HLS文件通过Docker共享卷共享。
失败的FFmpeg命令
ffmpeg -re -i "/var/www/html/hls/.m3u8" -c:a aac -ar 44100 -ab 128k -ac 2 -strict -2 -flags +global_header -bsf:a aac_adtstoasc -bufsize 3000k -f flv "rtmp://a.rtmp.youtube.com/live2/live_key"
错误信息
[tcp @ 0x696d2c0] Failed to resolve hostname a.rtmp.youtube.com: System error [rtmp @ 0x696d480] Cannot open connection tcp://a.rtmp.youtube.com:1935?tcp_nodelay=0 [out#0/flv @ 0x6890880] Error opening output rtmp://a.rtmp.youtube.com/live2/live_key: Input/output error Error opening output file rtmp://a.rtmp.youtube.com/live2/live_key. Error opening output files: Input/output error
成功的FFmpeg命令(使用IP而非域名)
ffmpeg -re -i "/var/www/html/hls/.m3u8" -c:a aac -ar 44100 -ab 128k -ac 2 -strict -2 -flags +global_header -bsf:a aac_adtstoasc -bufsize 3000k -f flv "rtmp://74.125.203.134/live2/live_key"
已尝试的操作
- 在主机运行FFmpeg:在macOS主机上安装FFmpeg并运行如下命令,可正常推流,说明问题仅存在于Docker容器环境:
ffmpeg -re -i "http://localhost:8080/hls/.m3u8" -c:a aac -ar 44100 -ab 128k -ac 2 -strict -2 -flags +global_header -bsf:a aac_adtstoasc -f flv "rtmp://a.rtmp.youtube.com/live2/live_key" - DNS解析测试:在PHP容器内执行
nslookup a.rtmp.youtube.com可获取多个IP地址,说明DNS解析功能正常:nslookup a.rtmp.youtube.com Server: 240b:11:cc40:d500:23a:9dff:fe92:75a8 Address: 240b:11:cc40:d500:23a:9dff:fe92:75a8#53 Non-authoritative answer: Name: a.rtmp.youtube.com Address: 74.125.203.134 ...
请问是什么原因导致Docker容器内的FFmpeg推流YouTube Live时出现域名解析失败?如何解决该问题,使FFmpeg命令可正常使用域名?
原因分析与解决办法
核心原因
你使用的是静态编译版FFmpeg(从johnvansickle下载的),这类静态编译包默认禁用了系统DNS解析库,改用内置的解析逻辑,但在Docker容器的网络环境下,内置逻辑无法正常读取系统DNS配置,导致域名解析失败。而容器内的nslookup用的是系统自带的解析工具,所以能正常工作;主机上的FFmpeg是动态编译,依赖系统DNS库,因此也没问题。
解决办法
方法1:改用动态编译版FFmpeg替换静态版
修改Dockerfile,通过系统包管理器安装FFmpeg(动态编译,依赖系统库):
FROM php:apache COPY --from=composer /usr/bin/composer /usr/bin/composer # 替换静态FFmpeg为系统包 RUN apt-get update && apt-get install -y --no-install-recommends ffmpeg && \ rm -rf /var/lib/apt/lists/*
重新构建PHP容器:docker-compose build php,之后再运行FFmpeg命令即可正常解析域名。
方法2:给静态FFmpeg指定DNS服务器
如果坚持使用静态FFmpeg,可以在FFmpeg命令中手动指定DNS服务器,强制其使用正确的解析地址:
ffmpeg -re -i "/var/www/html/hls/.m3u8" -c:a aac -ar 44100 -ab 128k -ac 2 -strict -2 -flags +global_header -bsf:a aac_adtstoasc -bufsize 3000k -f flv -dns 8.8.8.8 "rtmp://a.rtmp.youtube.com/live2/live_key"
这里用了Google的公共DNS(8.8.8.8),也可以替换成你容器内nslookup显示的服务器地址。
方法3:配置Docker容器的DNS优先级
检查Docker的DNS配置,确保容器优先使用IPv4 DNS而非IPv6:
- 在
docker-compose.yml的php服务中添加DNS配置:
services: php: # ... 其他配置 dns: - 8.8.8.8 - 8.8.4.4
- 重启容器:
docker-compose down && docker-compose up -d
静态FFmpeg可能会优先尝试IPv6解析,而部分网络环境下IPv6不通,指定IPv4 DNS可以避免这个问题。
内容的提问来源于stack exchange,提问作者Jun

