maz
January 6, 2022, 1:48pm
1
I need to call out to ffmpeg and ffprobe to process a file that I upload(Phoenix 1.6 app). Works fine in development environment but when I try to call System.cmd() from the running container in production the result is :enoent
I’m pretty sure this is because the docker container does not have the binaries available to it(I just put the in the root project dir in the development environment).
How do I make these available to the container? I presume the correct permissions should be set also?
Well, you can append the project root to the PATH inside the container?
Best way is probably to copy the required binaries to the right location in your image when you build the image using the Dockerfile COPY
command.
How are you building the image?
Alternatively, if the binaries you’re trying to call can be installed using the package manager of the distribution your image is based on, that should be even better. So something like:
apk add my_binary_package
in your Dockerfile, if you’re using an Alpine-based image
maz
January 6, 2022, 7:54pm
5
Yes I’m using an alpine based image and I’m almost there with your suggestion to apk add
them:
here is the first portion of my Dockerfile(link to full Dockerfile below):
# STEP 1 - BUILD RELEASE
# cannot use alpine 3.14.0 because of issue here with bcrypt-elxir compiling using make on docker:
# https://github.com/riverrun/bcrypt_elixir/issues/26#issuecomment-881966412
FROM hexpm/elixir:1.12.3-erlang-24.0.6-alpine-3.13.5 AS build
# install build dependencies
RUN apk add --update git \
build-base \
ffmpeg \
--update npm
RUN apk add ffprobe --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community
I can fetch ffmpeg
OK:
RUN apk add --update git \
build-base \
ffmpeg \
--update npm
but putting ffprobe \
in the above command results in:
ffprobe (no such package):
I also tried:
RUN apk add ffprobe --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community
but same error.
I can try copying over the ffprobe that I have in the second build phase but how do I know what binary to download that will run on alpine? I am aware of this page: FFbinaries - Download binaries for ffmpeg, ffprobe, ffserver and ffplay (cross-platform: Windows, Mac, Linux)
I noticed that the owner and group are nobody
, which appears to “smell” to me:
bash-5.1$ ls -ls
total 72856
8 drwxr-xr-x 1 nobody nobody 4096 Jan 6 19:10 bin
4 -rwxr-xr-x 1 nobody nobody 602 Oct 18 03:02 entrypoint.sh
8 drwxr-xr-x 1 nobody nobody 4096 Jan 6 19:10 erts-12.0.4
72816 -rwxr-xr-x 1 nobody nobody 74563488 Sep 7 2019 ffprobe
8 drwxr-xr-x 1 nobody nobody 4096 Jan 6 19:10 lib
8 drwxr-xr-x 1 nobody nobody 4096 Jan 6 19:10 releases
4 drwxr-xr-x 2 nobody nobody 4096 Jan 6 19:12 tmp
Full Dockerfile:
Not familiar with ffmpeg/ffprobe, but according to this:
https://pkgs.alpinelinux.org/contents?branch=edge&name=ffmpeg&arch=x86&repo=community
it looks like ffprobe
is part of the ffmpeg
package.
In fact, I just installed the ffmpeg
package in a local alpine container and I was able to run both binaries (ffmpeg
and ffprobe
). Give it a try.
1 Like
maz
January 6, 2022, 8:55pm
7
Yeah you’re right. However despite that System.cmd() just doesn’t see it. I put it a trivial call to ffmpeg
from mount()
home page:
ffmpeg = System.cmd("ffmpeg", ["-v"], [stderr_to_stdout: true])
IO.inspect(ffmpeg, label: "ffmpeg output")
faithful_word | Server: localhost:4000 (http)
faithful_word | Request: GET /
faithful_word | ** (exit) an exception was raised:
faithful_word | ** (ErlangError) Erlang error: :enoent
faithful_word | (elixir 1.12.3) lib/system.ex:1041: System.cmd("ffmpeg", ["-v"], [stderr_to_stdout: true])
faithful_word | (faithful_word 0.1.0) lib/faithful_word_web/live/landing_live/landing_page.ex:95: FaithfulWordWeb.Pages.Landing."mount (overridable 1)"/3
I don’t get it heh
Probably because it can’t find the executable in the PATH
env variable.
Try to pass it the absolute path to the executable:
System.cmd("/usr/bin/ffmpeg", ...)
1 Like
maz
January 6, 2022, 9:44pm
9
Yeah good point. getting a similar error:
faithful_word | Server: localhost:4000 (http)
faithful_word | Request: GET /
faithful_word | ** (exit) an exception was raised:
faithful_word | ** (ErlangError) Erlang error: :enoent
faithful_word | :erlang.open_port({:spawn_executable, '/usr/bin/ffmpeg'}, [:stderr_to_stdout, :use_stdio, :exit_status, :binary, :hide, {:args, ["-v"]}])
faithful_word | (elixir 1.12.3) lib/system.ex:1052: System.do_cmd/3
When I docker exec -ti faithful_word bash
into the running container I don’t see the ffmpeg binary:
bash-5.1$ pwd
/usr/bin
bash-5.1$ ls
[ cmp du getconf logger nproc pgrep seq tac uniq wc
[[ comm eject getent lsof nsenter pkill setkeycodes tail unix2dos wget
awk cpio env groups lsusb nslookup pmap setsid tee unlink which
basename createdb expand hd lzcat od printf sha1sum test unlzma whoami
bc createuser expr head lzma openssl pscan sha256sum time unlzop whois
beep crontab factor hexdump lzopcat openvt psql sha3sum timeout unshare xargs
blkdiscard cryptpw fallocate hostid md5sum passwd pstree sha512sum top unxz xxd
bunzip2 cut find iconv mesg paste pwdx showkey tr unzip xzcat
bzcat dc flock id microcom pg_basebackup readlink shred traceroute uptime yes
bzip2 deallocvt fold install mkfifo pg_dump realpath shuf traceroute6 uudecode
cal diff free ipcrm mkpasswd pg_dumpall reindexdb sort truncate uuencode
chvt dirname fuser ipcs nc pg_isready renice split tty vacuumdb
cksum dos2unix gdbm_dump killall nl pg_receivewal reset ssl_client ttysize vi
clear dropdb gdbm_load ldd nmeter pg_recvlogical resize strings udhcpc6 vlock
clusterdb dropuser gdbmtool less nohup pg_restore scanelf sum unexpand volname
which explains why I get :enoent
but I wonder why the binary is not there.
maz
January 6, 2022, 9:53pm
10
OK I got it! The issue was that I was adding the ffmpeg
binary during the build phase and not the runtime dependency phase(naturally). This fixed it:
####################################################################################################
# STEP 2 - FINAL
FROM alpine:3.13.5 as app
# install runtime dependencies
# https://stackoverflow.com/questions/68010688/docker-run-error-loading-shared-library-libstdc-so-6-and-libgcc-s-so-1
RUN apk upgrade --no-cache && \
apk add --update bash \
openssl \
ffmpeg \
postgresql-client \
libstdc++
Thanks for your help!
1 Like