Tenho alguns pontos, principalmente em relação ao Docker, que tenho mais afinidade (front-end não é o meu forte).
1 - Por que usar node 13? Nem é LTS e tá depreciado. A maioria dos serviços em nuvem usam o 14 ou estão migrando pro 16.
2 - Acho que deveria ser .gitignore (com ponto);
3 - Falando em ignore, não vi um .dockerignore, o que me leva ao 4º ponto;
4 - Vi que você literalmente faz COPY . /app , ou seja, copia tudo pra dentro da imagem, inclusive arquivos desnecessários (*.md, *.yml, e até *.env - PERIGOSÍSSIMO) e até sensíveis. Já pensou se alguém usa seu Dockerfile e publica uma imagem no DockerHub. O cara poderia estar expondo, por exemplo, configurações de banco de dados presentes .env; Sobre COPY . /app, vamos ao 5º ponto;
5 - Sugiro você dar uma estudada em multi-stage build. A ideia é reduzir o tamanho final da sua imagem. Pra isso, devemos colocar na imagem somente o NECESSÁRIO pra rodar a aplicação (o ideal é não ter código, é só ter o binário final. Assim a imagem final é a imagem base + o binário). Nunca fiz um projeto só com React, onde trabalho usamos NextJS, então não sei se React tem uma etapa de build. Se você quiser um exemplo prático com NextJS, pode olhar aqui. Posso resumir em 3 steps:
- npm install (instalação dos pacotes);
- npm run build (geração de arquivos estáticos e outros bla-bla-blas);
- npm run start (roda somente com os arquivos de /node_modules e arquivos otimizados do run build). Esse start é somente para production. Ou seja, o teu node_modules não terá pacotes development do package.json;
6- Você poderia ter somente um Dockerfile. Usando um ARG daria pra dizer se é production ou development. Mesma coisa pro docker-compose. Daria pra ser somente um. Você poderia colocar development e production como se fossem serviços diferentes. No link que mandei tem esse exemplo.
Acho que é isso. Não posso falar sobre a parte do React, já que não é o meu forte rsrs.