Introdução
O .NET é relativamente novo no mundo do código-fonte aberto e sua popularidade não chega nem perto das plataformas convencionais, como o Node.js. Então você pode imaginar que existem poucos tutoriais que lidam com .NET e estruturas como o ASP.NET no Heroku. E aqueles que o fazem, provavelmente não usarão contêineres.

Você vê C # /. NET aqui? Sim, eu também não.
Introdução
Este tutorial pressupõe que você tenha as ferramentas Docker, .NET Core e Heroku instaladas. Usarei Linux (Ubuntu), mas o AFAIK essas ferramentas são multiplataforma, portanto, as etapas serão as mesmas para qualquer sistema operacional suportado.
Vamos considerar o caso mais fácil - o aplicativo MVC simples. Se você não tiver um, basta criá-lo executando
dotnet new mvc --name mymvc
Também assumirei que você tem um arquivo docker pronto, talvez algo como o proposto neste tutorial :
FROM mcr.microsoft.com/dotnet/core/sdk:2.2 AS builder WORKDIR /sources COPY *.csproj . RUN dotnet restore COPY . . RUN dotnet publish --output /app/ --configuration Release FROM mcr.microsoft.com/dotnet/core/aspnet:2.2 WORKDIR /app COPY --from=builder /app . CMD ["dotnet", "MyMvc.dll"]
Observe como o ENTRYPOINT foi substituído pelo CMD - mais sobre isso posteriormente.
Então, CD para a pasta do seu aplicativo e vamos começar.
Entre no registro de contêiner Heroku.
heroku container:login
Se você não possui um repositório git existente, git init
um novo
Execute o heroku create
para criar um novo aplicativo, observe o endereço de heroku create
git fornecido, por exemplo
Creating salty-fortress-4191... done, stack is heroku-16 https://salty-fortress-4191.herokuapp.com/ | https://git.heroku.com/salty-fortress-4191.git
(Opcional) Verifique se você possui o heroku remote executando git remote -v
Diga ao Heroku para usar contêineres:
heroku stack:set container
Crie o arquivo heroku.yml. Versão minimalista é algo como:
build: docker: web: Dockerfile
Por padrão, o núcleo do ASP.NET é executado nas portas 5000 e 5001 (https). Heroku não permitirá isso. Se você tentar executá-lo como está, o Kestrel não será iniciado, lançando uma exceção:
System.Net.Sockets.SocketException (13): Permission denied
O Heroku parece permitir que o aplicativo ouça na porta especificada na variável de ambiente $PORT
. Portanto, você precisa garantir que seu aplicativo ouça isso, em vez do padrão. Caso você esteja usando o aplicativo padrão, substitua CreateWebHostBuilder
pelo seguinte em Program.cs
:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) { var port = Environment.GetEnvironmentVariable("PORT"); return WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseUrls("http://*:"+port); }
Confirme tudo:
git add . && git commit -m 'Meaningful commit message'
Agora empurre o código para obter o container construído e liberado (dedos cruzados):
git push heroku master
Agora lembra-se de quando ENTRYPOINT foi substituído pelo CMD no dockerfile? Como não passamos nenhum argumento para o contêiner, então ENTRYPOINT ["dotnet", "MyMvc.dll"]
e CMD ["dotnet", "MyMvc.dll"]
devem se comportar da mesma maneira. Mas se você deixar ENTRYPOINT, receberá um erro:

Que grande erro - "Status de resposta de atualização inesperada de formatação"! Realmente lhe diz a raiz do problema.
O verdadeiro problema é que, ao usar o heroku.yml
minimalista que mostrei acima, o Heroku esperará instruções sobre CMD no seu dockerfile. Quando você o adiciona, tudo deve funcionar bem.
Conclusão
Agora você deve ter alguma idéia de como implantar aplicativos simples do ASP.NET Core no Heroku. É intuitivo? Absolutamente não. O Heroku é a melhor plataforma para hospedar seus aplicativos .NET? Provavelmente não. Mas como é fácil se inscrever lá e o plano mais básico é gratuito - talvez você queira hospedar algo lá, apenas por diversão.
Referências
- https://devcenter.heroku.com/articles/container-registry-and-runtime
- https://devcenter.heroku.com/articles/build-docker-images-heroku-yml
- https://docs.docker.com/engine/examples/dotnetcore/ (Dockerfile)