The problem is passing the environment variable, not how you set it (dotenv or not) or how you use it (to set a variable or COPY). 
Here's a complete demo with the technique from the duplicate. This is script.sh:
#!/bin/bash
mycustomvar="file.$RANDOM"
touch "$mycustomvar"
echo "I am running outside Docker with mycustomvar=$mycustomvar"
docker build --build-arg mycustomvar="$mycustomvar" .
And a Dockerfile:
FROM alpine
ARG mycustomvar
RUN echo "I am running in docker with mycustomvar=$mycustomvar"
COPY $mycustomvar /tmp/
RUN ls /tmp
Here's what happens when you run it:
$ sudo ./script.sh
I am running outside Docker with mycustomvar=file.10518
Sending build context to Docker daemon  17.41kB
Step 1/5 : FROM alpine
 ---> 3fd9065eaf02
Step 2/5 : ARG mycustomvar
 ---> Using cache
 ---> a6dfa6001164
Step 3/5 : RUN echo "I am running in docker with mycustomvar=$mycustomvar"
 ---> Running in e958044bfd11
I am running in docker with mycustomvar=file.10518
 ---> 95c107e49291
Removing intermediate container e958044bfd11
Step 4/5 : COPY $mycustomvar /tmp/
 ---> d36445b49261
Removing intermediate container e3ac014d1ba9
Step 5/5 : RUN ls /tmp
 ---> Running in 590409a81df5
file.10518
 ---> d734f83cc8ec
Removing intermediate container 590409a81df5
Successfully built d734f83cc8ec
As you can see, script.sh sets a variable, and the RUN and COPY statements both have access to it.