zsh isn't necessarily installed in a Docker image. If you're using an Alpine-based image, it won't even have bash. In most cases, you need to change the "shebang" line to #!/bin/sh, and it will work on any Linux Docker image (provided it includes a shell; scratch and "distroless" images don't even have that).
#!/bin/sh
# ^^^^^^^ canonical path of the Bourne shell
echo "Hello"
This means that you need to limit yourself to the features of the POSIX shell (though this is generally good practice). That syntax doesn't include array-typed variables or some substitution syntaxes, and it doesn't support alternate command spellings like source (use . instead). The basic script you have here will work just fine.
You should make the script executable on the host system and check it into source control that way. Both typical source-control systems (e.g., Git) and docker build will preserve this permission setting; you don't normally need to RUN chmod.
I'd then tweak the Dockerfile to
FROM ubuntu:latest
WORKDIR /app
COPY main.sh ./ # target the current WORKDIR; don't repeat the absolute path
CMD ["./hello.sh"] # JSON-array syntax is very slightly more efficient
With the correct executable bit and shebang line, you do not need to state the interpreter; do not say sh hello.sh.
zshinstalled at/usr/bin/zsh#!/usr/bin/env zshor#!/usr/bin/env bashinstead.