Hoje fui experimentar o suporte a contêineres no Windows. A ideia ainda é nova e a única versão estável ainda não está totalmente pronta, está disponível somente no Windows Server 2016 Technical Preview 4. O Windows Server 2016 ainda não foi lançado. Aproveitei para ver como estava o suporte a Docker.

Vou mostrar abaixo como você cria o Nano Server, como loga, e como cria contêineres.

Esse artigo do Technet dá uma boa explicacão, e foi por onde eu comecei. Mas tem muita informação por lá. Vou facilitar e dar o caminho mais simples para você criar o Nano Server virtualizado com HyperV.

A primeira coisa que você tem que saber é que não há uma imagem (.img ou .iso) de instalação ou um arquivo de vhd ou vhdx (disco do HyperV) prontos. Você precisa baixar o Windows Server 2016, e de lá mandar criar um vhd ou vhdx (prefiro já usar a nova versão com GPT e ir para vhdx). Esse vhdx já contém toda a configuração básica do Nano Server. Nesse momento você não consegue alterar o Nano Server criado, então precisa escolher direito que tipo de servidor você quer antes de iniciá-lo. É possível criar servidores de diversos tipos, como IIS, de contêineres, etc.

Criando o Nano Server

O artigo do technet explica, e basicamente o processo se dá montando a imagem do Server 2016 que você baixa do site da Microsft (en_windows_server_2016_technical_preview_4_x64_dvd_7258292.iso), e então, via Powershell, importando o módulo “\NanoServer\NanoServerImageGenerator.psm1”:

Import-Module "G:\NanoServer\NanoServerImageGenerator.psm1" -Verbose

No meu caso, montou no drive G.

Aí você já pode rodar o comando “New-NanoServerImage”. É esse comando que vai montar o vhdx. O que eu acabei descobrindo na 3a vez que crie o vhdx (pelo menos é rápido) é que o Nano Server é realmente muito simples. Nesse momento, você não consegue sequer baixar um arquivo da internet com ele, ou mesmo copiar um arquivo para ele. Assim, acabei por incluir também o suporte a shared folders (opção -Storage), para poder compartilhar uma pasta dele e então copiar arquivos dele e para ele.

O comando ficou assim:

New-NanoServerImage -MediaPath g: -BasePath C:\temp\nano\base -TargetPath c:\temp\nano\nanoservervm.vhdx -ComputerName Nano2016tp4 -GuestDrivers -Containers -ReverseForwarders -Storage

Com isso, ele criou o vhdx no caminho c:\temp\nano\nanoservervm.vhdx. A máquina sobe com o nome que eu dei pra ela, Nano2016tp4, com ip dinâmico, e suportando contêineres (opção -Containers). É importante não esquecer essa opção.

Depois foi só mover ele pra pasta que eu queria e criar a VM no HyperV. Isso é o suficiente pra criar um Nano Server. Bem simples, certo? Quando ele subir, vai entrar na tela de login. E ele sobe rápido. Muito rápido. O tempo total, do ponto em que você dá a ordem de iniciar, até ele estar disponível, é de 10 segundos. Desconsiderando o tempo de inicio da máquina em si, e da configuração da BIOS, leva entre 5 e 6 segundos. E ela desliga de forma praticamente imediata, há espera zero. Abaixo um gif animado para vocês verem (clique para ampliar).

Boot do Nano Server

Mas nem se anime de usar ele por ali. Pelo menos não muito. Essa é a chamada “Recovery Console”, e nela não é possível fazer muita coisa. O que essa console permite fazer é somente auxiliar na configuração do server para que seja acessado remotamente, que é como ele deve ser administrado. Assim, é possível verificar as configurações de rede, e atualizá-las, assim como o firewall, além de reiniciar a máquina. Nada além disso. Não há um shell que você possa usar, seja ela cmd, powershell, bash, ou o que for.

Para acessá-lo, a melhor opção é o remote powershell. Imagino que deve ser possível usar ferramentas gráficas de administração, também, mas nem tentei. Mas há umas pegadinhas. Minha máquina não estava preparada, e precisei rodar o quickconfig do Windows Remote Management, assim:

winrm quickconfig

Lembrando que é importante rodar esses comandos com um powershell de administrador da máquina (botão direito, Run as Administrator).

Após isso, você precisa acrescentar essa máquina às máquinas confiáveis. Você faz isso assim:

Set-Item WSMan:\localhost\Client\TrustedHosts "192.168.137.80"

Agora sim, você já vai pode acessá-lo.

Enter-PSSession -ComputerName "192.168.137.80" -Credential administrator

Ele vai te solicitar a senha em seguida. Isso vai mantê-lo na mesma janela de Powershell, mas agora no server remoto. E pronto, já estará usando o Nano Server.

Na console remota você pode criar e configurar o File Share. Via Powershell, lógico. Rode:

New-SmbShare -Name C -Path c:\
Grant-SmbShareAccess -Name c -AccountName Administrators -AccessRight Full -Force

E agora você já pode acessar “\\192.168.137.80\c” e gravar ou ler o que quiser por lá.

Configurando o serviço de contêineres e baixando uma imagem

A feature de contêineres já vai estar instalada, mas você ainda precisa ser capaz de baixar e instalar contêineres. Não é preciso docker pra isso, você pode fazer via Powershell. A primeira coisa é instalar um provider para o OneGet (que é como um apt-get ou chocolatey, mas nativo no Windows Server 2016 e Windows 10). Assim:

Install-PackageProvider ContainerProvider -Force

Isso irá disponibilizar diversos comandos para gestão de contêineres que você não tinha antes. Para listar os contêineres que você pode instalar, rode:

Find-ContainerImage

Para instalar a imagem de um outro Nano Server, rode:

Install-ContainerImage -Name NanoServer -Version 10.0.10586.0

Não foi possível, para mim, baixar a imagem do Windows Server Core pra rodar no Nano. Talvez não seja suportado no momento. O comando abaixo não funciona, e retorna “Unable to download.”.

Install-ContainerImage -Name WindowsServerCore -Version 10.0.10586.0

Para ver a imagem disponível, rode:

Get-ContainerImage

Para se comunicar via rede com o contêiner, você precisa de uma rede virtual no Nano Server. Você cria ela com o New-VMSwitch:

New-VMSwitch -Name "Virtual Switch" -SwitchType NAT -NATSubnetAddress 172.16.0.0/12

Criando e iniciando um contêiner

Criar o contêiner é fácil, basta informar o nome da rede e do contêiner que será usado como base:

New-Container -Name TP4Demo -ContainerImageName NanoServer -SwitchName "Virtual Switch"

Para iniciá-lo:

Start-Container TP4Demo

E para logar nele com o Powershell:

Enter-PSSession -ContainerName TP4Demo -RunAsAdministrator

Abaixo você vê tudo isso funcionando em outro gif animado (clique para ampliar):

nano container

Rodando via docker

Consegui fazer o docker rodar como serviço no Windows, e quase não consegui fazê-lo conversar com o serviço de contêineres do Windows. Os docs dão o caminho, mas não funcionou de imediato. Quando voltei depois no server estava funcionando. O que acontecia é que o docker não listava as imagens instaladas pelo Powershell. E cuidado com esses docs, eles não foram feitos para Nano Server, mas para no mínimo Server Core, que tem bem mais serviços disponíveis. Um exemplo é o “wget”, que não funciona no Nano Server.

A primeira coisa é baixar o docker.exe e colocá-lo no C:\windows\system32\docker.exe. Faça isso usando o file share que criamos antes e o docker.exe que está em https://aka.ms/tp4/docker. Depois crie o arquivo “C:\ProgramData\Docker\runDockerDaemon.cmd” com o seguinte conteúdo:

@echo off
set certs=%ProgramData%\docker\certs.d

if exist %ProgramData%\docker (goto :run)
mkdir %ProgramData%\docker

:run
if exist %certs%\server-cert.pem (goto :secure)

docker daemon -D -b "Virtual Switch" -H 0.0.0.0:2375
goto :eof

:secure
docker daemon -D -b "Virtual Switch" -H 0.0.0.0:2376 --tlsverify --tlscacert=%certs%\ca.pem --tlscert=%certs%\server-cert.pem --tlskey=%certs%\server-key.pem

Os docs também indicam o uso do aplicativo nssm para criar o serviço Windows do docker. Ele não roda no Nano Server. Use o powershell pra criar o serviço. A única coisa que vai faltar, que o nssm faz e o powershell não faz, é o IO redirect para um arquivo de log.

New-Service -Name Docker -BinaryPathName "C:\Windows\System32\cmd.exe /s /c C:\ProgramData\Docker\runDockerDaemon.cmd" -DisplayName "Docker Daemon" -StartupType Automatic -Description "This is the docker daemon"

Você ainda precisa abrir o firewall. As portas usadas normalmente pelo docker são as 2375 e 2376:

netsh advfirewall firewall add rule name="Docker 2375" dir=in action=allow protocol=TCP localport=2375
netsh advfirewall firewall add rule name="Docker 2376" dir=in action=allow protocol=TCP localport=2376

Ou se preferir, libere o exe do docker diretamente:

netsh advfirewall firewall add rule name="Allow Docker" dir=in action=allow program="C:\windows\system32\docker.exe"

E inicie o serviço:

Start-Service docker

Para ver se o serviço subiu corretamente:

Get-Service Docker

Notei que o serviço sobe e que você consegue se conectar com ele, mesmo remotamente.

Abaixo vocês vêem mais um gif animado (por que não, certo?) do Docker rodando no Windows Server, sendo chamado de um Windows 10, que também é o Host da VM do Windows Server (clique para ampliar):

Nano rodando docker

Note que subi o CMD, não o Powershell, via Docker. Não é possível subir o Powershell. Mesmo depois que iniciei o contêiner, não foi possível entrar no REPL do Powershell.

A impressão que tive foi de que ele ainda não existe, e a versão que está no Nano Server é somente para executar scripts, sem um REPL, e é baseada no .NET Core.

Você encontra mais informações sobre o Docker com um Host Windows neste artigo do Technet.

Suporte no Azure

O Nano Server já vem com suporte no Azure. O script de criação do NanoServer que mostrei antes (New-NanoServerImage) já tem uma opção para deixar o VHD pronto para o Azure (-ForAzure). Além disso, há um template pronto para criar uma nova máquina com Nano:

Nano no azure

O problema é que esse template não tem as opções que o script de criação tem, assim, é só pra experimentar rapidamente mesmo. Pra testes mais sérios, vale mais a pena criar o VHD e subir pro Azure. Ele não fica muito grande, tem menos de 1GB.

Problemas com a VM e uma placa wireless

Tive outro problema com o HyperV e uma placa wireless. As máquinas virtuais acabavam sempre pegando o mesmo IP do Host. Resolvi isso criando uma rede interna no HyperV (que não se comunica com a internet – olhe o Virtual Switch Manager) e fazendo compartilhamento da internet da placa wireless com a placa interna:

Internet Sharing

Com isso, a VM sempre pega o IP que o DHCP do compartilhamento entrega, que é da rede 192.168.137.0/24. No meu caso, começando do .79. A VM do Nano é a segunda, e pego o .80.

Conclusões

Gostei do que vi, mas deu trabalho pra fazer funcionar. Não se compara ainda com a facilidade do Docker, que se instala com um único script no Linux, e não demanda outra infra além da que ele mesmo configura. Espero que essa praticidade chegue no Windows em algum momento. O legal foi fazer as coisas funcionarem, é um grande avanço, e lembrando, é tudo ainda tecnologia que está em Preview. Vamos aguardar a evolução do Windows Server 2016 e do Nano Server junto, e também a do Docker no Windows.

Espero que em breve possamos começar a fazer um uso de contêineres também no Windows. As vantagens são imensas, e no Linux é a minha primeira opção de delivery de aplicações, sem nem pensar duas vezes. As que eu mais gosto são a possibilidade de rodar inúmeras “máquinas” pagando apenas uma máquina em um host qualquer como o Azure, permitindo uma economia gigantesca (excelente para pequenas aplicações), e também a possilibilidade de ter o ambiente de desenvolvimento quase idêntico ao de produção.

E vocês, o que acharam? Já tinham visto contêineres no Windows? E no Linux? Contem aí nos comentários. Pra quem se interessar, tem uma tag só de docker aqui no blog, inclusive com vídeos mostrando como usar. Divirtam-se.

Giovanni Bassi

Arquiteto e desenvolvedor, agilista, escalador, provocador. É fundador e CSA da Lambda3. Programa porque gosta. Acredita que pessoas autogerenciadas funcionam melhor e por acreditar que heterarquia é mais eficiente que hierarquia. Foi reconhecido Microsoft MVP há mais de dez anos, dos mais de vinte que atua no mercado. Já palestrou sobre .NET, Rust, microsserviços, JavaScript, TypeScript, Ruby, Node.js, Frontend e Backend, Agile, etc, no Brasil, e no exterior. Liderou grupos de usuários em assuntos como arquitetura de software, Docker, e .NET.