As respostas existentes cobrem a maior parte do que qualquer pessoa que esteja olhando para essa pergunta precisaria. Então, abordarei algumas áreas de nicho para CMD e RUN.
CMD: duplicatas são permitidas, mas desperdiçam
O GingerBeer faz uma observação importante: você não receberá nenhum erro se colocar mais de um CMD - mas é um desperdício fazê-lo. Eu gostaria de elaborar com um exemplo:
FROM busybox
CMD echo "Executing CMD"
CMD echo "Executing CMD 2"
Se você criar isso em uma imagem e executar um contêiner nessa imagem, como GingerBeer afirma, apenas o último CMD será atendido. Portanto, a saída desse contêiner será:
Executando o CMD 2
A maneira como penso é que "CMD" está definindo uma única variável global para toda a imagem que está sendo criada, de modo que sucessivas instruções "CMD" simplesmente substituem quaisquer gravações anteriores nessa variável global e, na imagem final criada, último a escrever vitórias. Como um Dockerfile é executado em ordem de cima para baixo, sabemos que o CMD mais baixo é aquele que obtém essa "gravação" final (metaforicamente falando).
EXECUÇÃO: comandos podem não executar se as imagens estiverem em cache
Um ponto sutil a ser observado sobre o RUN é que ele é tratado como uma função pura, mesmo que haja efeitos colaterais e, portanto, é armazenado em cache. O que isso significa é que, se o RUN tiver alguns efeitos colaterais que não alteram a imagem resultante e essa imagem já tiver sido armazenada em cache, o RUN não será executado novamente e, portanto, os efeitos colaterais não ocorrerão nas construções subseqüentes. Por exemplo, considere este Dockerfile:
FROM busybox
RUN echo "Just echo while you work"
Na primeira vez em que você o executa, você obtém resultados como este, com diferentes IDs alfanuméricos:
docker build -t example/run-echo .
Sending build context to Docker daemon 9.216kB
Step 1/2 : FROM busybox
---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
---> Running in ed37d558c505
Just echo while you work
Removing intermediate container ed37d558c505
---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest
Observe que a instrução echo foi executada acima. Na segunda vez que você o executa, ele usa o cache e você não verá nenhum eco na saída da compilação:
docker build -t example/run-echo .
Sending build context to Docker daemon 9.216kB
Step 1/2 : FROM busybox
---> be5888e67be6
Step 2/2 : RUN echo "Just echo while you work"
---> Using cache
---> 6f46f7a393d8
Successfully built 6f46f7a393d8
Successfully tagged example/run-echo:latest