Essa pergunta também seria pertinente para o golang, onde você pode extrair binários vinculados estaticamente e executá-los em algum lugar, em vez de Python ou C ++, onde você normalmente tem um grande número de bibliotecas vinculadas, o que leva as pessoas a criar apenas um contêiner de docker a partir do diretório ambiente de desenvolvimento.
Há dois pontos a serem respondidos aqui:
Um: deve haver uma maneira melhor , e existe: você pode criar contêineres menores (e mais eficientes) usando apenas o ambiente de instalação, o que leva a vantagens semelhantes, como no caso Golang com ambiente versus Golang apenas - recipientes binários. No caso do Java, você pode criar um jar gordo ou um aplicativo instalável que contenha todos os jarros da biblioteca e um script de shell; no caso do Python, você pode usar o auditwheel para criar rodas independentes que são independentes do ambiente de construção (e você pode usar o C ++ com vinculação estática para quase o mesmo efeito).
Dois: para que você precisa do docker? Em Java, é possível fazer muita separação entre diferentes componentes usando carregadores de classes, mas o ponto principal é o que há em torno do aplicativo Java. Nenhum aplicativo Java é executado por si só - se não for executado no docker, normalmente precisará ser supervisionado pela supervisord ou systemd ou similares. Digite a nuvem Kubernetes, Marathon ou Docker, que usa a abstração de contêiner para virtualizar não o próprio host, mas virtualiza toda a rede de forma que você possa implantar contêineres e eles executarem em algum host aleatório.
Os microsserviços geralmente são executados em nuvens baseadas em janela de encaixe, pois permitem tratar os hosts da janela de encaixe como gado, não como animais de estimação e da mesma forma com os aplicativos com encaixe. Obviamente, essa abstração fica com vazamento assim que você monta volumes do host na janela de encaixe e precisa executar contêineres na janela de encaixe exatamente no host que possui esses volumes. Algumas pessoas se esquecem disso.