{"id":3766,"date":"2023-09-07T14:12:41","date_gmt":"2023-09-07T19:12:41","guid":{"rendered":"https:\/\/fgiasson.com\/blog\/?p=3766"},"modified":"2023-09-07T14:12:41","modified_gmt":"2023-09-07T19:12:41","slug":"how-to-deploy-hugging-face-models-in-azure-using-terraform-and-docker","status":"publish","type":"post","link":"https:\/\/fgiasson.com\/blog\/index.php\/2023\/09\/07\/how-to-deploy-hugging-face-models-in-azure-using-terraform-and-docker\/","title":{"rendered":"How to Deploy Hugging Face Models in Azure using Terraform and Docker"},"content":{"rendered":"\n<p>In a previous blog post, <a href=\"https:\/\/fgiasson.com\/blog\/index.php\/2023\/08\/23\/how-to-deploy-hugging-face-models-in-a-docker-container\/\">I explained how we can easily deploy Hugging Face models in Docker containers<\/a>. In this new post, I will explain how we can easily deploy that container in <a href=\"https:\/\/azure.microsoft.com\/en-ca\/\">Azure<\/a> using <a href=\"https:\/\/www.terraform.io\">Terraform<\/a>. At the end of this article, we will have end-to-end process that creates a translation service, containerize, deploy in the cloud and that is readily available on the Web in a single command in your terminal.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Create Free Azure Account<\/h3>\n\n\n\n<p>If you don&#8217;t currently have access to an Azure account, <a href=\"https:\/\/azure.microsoft.com\/en-ca\/free\/\">you can easily create one for free here<\/a>. You get a series of popular services for free for 12 months, 55 services free forever and 200$ USD in credit for a month. This is more than enough to run the commands in this tutorial. Even if none of those benefits would exists, it won&#8217;t be that much of a problem since you could create and tears down the services within a minute with <code>terraform destroy<\/code> which would incurs a few cents of usage.<\/p>\n<p>Finally, make sure that you <a href=\"https:\/\/learn.microsoft.com\/en-us\/cli\/azure\/install-azure-cli\">install the Azure CLI<\/a> command line tool.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install Terraform<\/h3>\n\n\n\n<p>The next step is to <a href=\"https:\/\/developer.hashicorp.com\/terraform\/tutorials\/azure-get-started\/install-cli\">install Terraform on your local computer<\/a>.<\/p>\n<p>Terraform is an infrastructure-as-code (IaC) tool that allows users to define and manage their cloud infrastructure in a declarative manner (i.e. the infrastructure that is described in a Terraform file is the end-state of that infrastructure in the Cloud). It automates the process of provisioning and managing resources across various cloud providers, enabling consistent and reproducible deployments.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using Terraform<\/h3>\n\n\n\n<p>This blog post is not meant to be an introduction to Terraform, so I will only cover the key commands that \u00a0I will be using. There are <a href=\"https:\/\/developer.hashicorp.com\/terraform\">excellent documentation by HashiCorp for developers<\/a> and there are excellent books such as <a href=\"https:\/\/www.amazon.ca\/Terraform-Running-Writing-Infrastructure-Code\/dp\/1098116747\/\">Terraform: Up and Running: Writing Infrastructure as Code<\/a> by Yevgeniy Brikman.<\/p>\n<p>The commands we will be using in this post are:<\/p>\n<ul>\n<li>\n<p><code>terraform plan<\/code>: It is used to preview the changes that Terraform will make to the infrastructure. It analyzes the configuration files and compares the desired state with the current state of the resources. It provides a detailed report of what will be added, modified, or deleted. It does not make any actual changes to the infrastructure.<\/p>\n<\/li>\n<li>\n<p><code>terraform apply<\/code>: It is used to apply the changes defined in the Terraform configuration files to the actual infrastructure. It will do the same as <code>terraform plan<\/code>, but at the end of the process it will prompt for confirmation before making any modifications. When we say <code>yes<\/code>, then all hells are breaking loose in the Cloud and the changes are applied by Terraform.<\/p>\n<\/li>\n<li>\n<p><code>terraform destroy<\/code>: It is used to destroy all the resources created and managed by Terraform. It effectively removes the infrastructure defined in the configuration files. It prompts for confirmation before executing the destruction.<\/p>\n<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Terraform file to deploy Hugging Face models on Azure<\/h3>\n\n\n\n<p>Now, let&#8217;s analyze the terraform file that tells Terraform how to create the infrastructure required to run the translation service in the Cloud.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Terraform Block<\/h4>\n\n\n\n<p>This <code>terraform<\/code> block is used to define the specific versions of Terraform and its providers. This ensure the reproducibility of the service over time, just like all the set versions of the libraries used for the translation service in Python.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>terraform {\n  required_version = &quot;&gt;= 1.5.6&quot; \n\n  required_providers {\n    azurerm = {\n      source  = &quot;hashicorp\/azurerm&quot;\n      version = &quot;&gt;= 3.71.0&quot;\n    }\n    null = {\n      source  = &quot;hashicorp\/null&quot;\n      version = &quot;&gt;= 3.2.1&quot;\n    }    \n  }\n}<\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">AzureRM Provider Block<\/h4>\n\n\n\n<p>This block configures the <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/azurerm\/latest\">AzureRM provider<\/a>. The <code>skip_provider_registration<\/code> prevents the provider from attempting automatic registration. The <code>features {}<\/code> specifies that no additional features for the provider are required for this demo.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>provider &quot;azurerm&quot; {\n  skip_provider_registration = &quot;true&quot;\n  features {}\n}<\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Resource Group Block<\/h4>\n\n\n\n<p>This block creates an <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/azurerm\/latest\/docs\/resources\/resource_group\">Azure Resource Group (ARG)<\/a>\u00a0named <code>translationarg<\/code> in the <code>eastus<\/code> region. The resource group is what is used to bundle all the other resources we will require for the translation service.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>resource &quot;azurerm_resource_group&quot; &quot;acr&quot; {\n  name     = &quot;translationarg&quot;\n  location = &quot;eastus&quot;\n}<\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Container Registry Block<\/h4>\n\n\n\n<p>This block creates an <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/azurerm\/latest\/docs\/resources\/container_registry\">Azure Container Registry (ACR)<\/a> named <code>translationacr<\/code>. It associates the ACR with the previously defined resource group, in the same region. The ACR is set to the &#8220;Standard&#8221; SKU. <code>admin_enabled<\/code> allows admin access to the registry.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>resource &quot;azurerm_container_registry&quot; &quot;acr&quot; {\n  name                     = &quot;translationacr&quot;\n  resource_group_name      = azurerm_resource_group.acr.name\n  location                 = azurerm_resource_group.acr.location\n  sku                      = &quot;Standard&quot;\n  admin_enabled            = true\n}<\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Null Resource for Building and Pushing Docker Image<\/h4>\n\n\n\n<p>This block uses the <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/null\/latest\">Null Provider<\/a> and defines a <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/null\/latest\/docs\/resources\/resource\"><code>null_resource<\/code><\/a> used for building and pushing the Docker image where the translation service is deployed. It has a dependence on the creation of the Azure Container Registry, which means that the ACR needs to be created before this resource. The <code>triggers<\/code> section is set to a timestamp, ensuring the Docker build is triggered on every Terraform apply. The <code>local-exec<\/code> provisioner runs the specified shell commands for building, tagging, and pushing the Docker image.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>resource &quot;null_resource&quot; &quot;build_and_push_image&quot; {\n  depends_on = [azurerm_container_registry.acr]\n\n  triggers = {\n    # Add a trigger to detect changes in your Docker build context\n    # The timestamp forces Terraform to trigger the Docker build,\n    # every time terraform is applied. The check to see if anything\n    # needs to be updated in the Docker container is delegated\n    # to Docker.\n    build_trigger = timestamp()\n  }\n\n  provisioner &quot;local-exec&quot; {\n    # Replace with the commands to build and push your Docker image to the ACR\n    command = &lt;&lt;EOT\n      # Build the Docker image\n      docker build -t en-fr-translation-service:v1 ..\/..\/\n      \n      # Log in to the ACR\n      az acr login --name translationacr\n      \n      # Tag the Docker image for ACR\n      docker tag en-fr-translation-service:v1 translationacr.azurecr.io\/en-fr-translation-service:v1\n      \n      # Push the Docker image to ACR\n      docker push translationacr.azurecr.io\/en-fr-translation-service:v1\n    EOT\n  }\n}<\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Container Group Block<\/h4>\n\n\n\n<p>This block creates an <a href=\"https:\/\/registry.terraform.io\/providers\/hashicorp\/azurerm\/latest\/docs\/resources\/container_group\">Azure Container Group (ACG)<\/a>. This is the resource used to create a container instance from a Docker container. It depends on the <code>null_resource<\/code> above for creating the image of the container and to make it available to the ACG.<\/p>\n<p>The <code>lifecycle<\/code> block ensures that this container group is replaced when the Docker image is updated. Various properties like name, location, resource group, IP address type, DNS label, and operating system are specified. The <code>image_registry_credential<\/code> section provides authentication details for the Azure Container Registry. A container is defined with its name, image, CPU, memory, and port settings. Those CPU and Memory are required for the service with the current model that is embedded in the Docker container. Lowering those values may result in the container instance to die silently with a out of memory error.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>resource &quot;azurerm_container_group&quot; &quot;acr&quot; {\n  depends_on = [null_resource.build_and_push_image]\n\n  lifecycle {\n    replace_triggered_by = [\n      # Replace `azurerm_container_group` each time this instance of\n      # the the Docker image is replaced.\n      null_resource.build_and_push_image.id\n    ]\n  }\n\n  name                = &quot;translation-container-instance&quot;\n  location            = azurerm_resource_group.acr.location\n  resource_group_name = azurerm_resource_group.acr.name\n  ip_address_type     = &quot;Public&quot;\n  dns_name_label      = &quot;en-fr-translation-service&quot;\n  restart_policy      = &quot;Never&quot;\n  os_type             = &quot;Linux&quot;\n\n  image_registry_credential {\n     username = azurerm_container_registry.acr.admin_username\n     password = azurerm_container_registry.acr.admin_password\n    server   = &quot;translationacr.azurecr.io&quot;\n  }\n\n  container {\n    name   = &quot;en-fr-translation-service-container&quot;\n    image  = &quot;translationacr.azurecr.io\/en-fr-translation-service:v1&quot;\n    cpu    = 4\n    memory = 8\n\n    ports {\n      protocol = &quot;TCP&quot;\n      port     = 6000\n    }\n  }\n\n  tags = {\n    environment = &quot;development&quot;\n  }\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Deploying the English\/French Translation Service on Azure<\/h3>\n\n\n\n<p>Now that we have a <a href=\"https:\/\/github.com\/fgiasson\/literate-en-fr-translation-service\/blob\/main\/terraform\/deploy\/main.tf\">Terraform file<\/a> that does all the work for us, how can we deploy the service on Azure?<\/p>\n<p>As simply as running this command line from the <code>\/terraform\/deploy\/<\/code> folder:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>terraform apply<\/code><\/pre><\/div>\n\n\n\n<p>Once we run that command, Terraform will analyze the file, and show everything that will changes in the Cloud infrastructure. In this case, we start from scratch, so all those resources will be created (none will change nor be destroyed):<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply.jpg\" alt=\"\" width=\"1390\" height=\"1840\" class=\"alignnone size-full wp-image-3777\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply.jpg 1390w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply-227x300.jpg 227w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply-774x1024.jpg 774w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply-768x1017.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply-1160x1536.jpg 1160w\" sizes=\"auto, (max-width: 1390px) 100vw, 1390px\" \/><\/a><\/p>\n<p>All the resources will then be created by Terraform. Those resources are created by communicating with Azure&#8217;s web service API. The output of each step is displayed in the terminal. The entire process to deploy four resources took about 12 minutes, 4 of which is to create the Docker image and 3 to create the Cloud resources and deploy the service. Most of the time is spent dealing with the somewhat big translation models that we baked in the Docker image:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished.jpg\" alt=\"\" width=\"2482\" height=\"898\" class=\"alignnone size-full wp-image-3779\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished.jpg 2482w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished-300x109.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished-1024x370.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished-768x278.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished-1536x556.jpg 1536w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_apply_finished-2048x741.jpg 2048w\" sizes=\"auto, (max-width: 2482px) 100vw, 2482px\" \/><\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the Translation Service on Azure<\/h3>\n\n\n\n<p>The next step is to test the service we just created on Azure.<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-bash\" data-lang=\"Bash\"><code>curl &quot;http:\/\/en-fr-translation-service.eastus.azurecontainer.io:6000\/translate\/fr\/en\/&quot; -H &quot;Content-Type: application\/json&quot; -d &#39;{&quot;fr_text&quot;:&quot;Bonjour le monde!&quot;}&#39;<\/code><\/pre><\/div>\n\n\n\n<p>The result we get from the service:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-json\" data-lang=\"JSON\"><code>{\n  &quot;en_text&quot;: &quot;Hello, world!&quot;\n}<\/code><\/pre><\/div>\n\n\n\n<p>It works! (well, why would I have spent the time to write this post if it didn&#8217;t?)<\/p>\n<p>A single command in your terminal to:<\/p>\n<ol>\n<li>Package a translation service and powerful translation models into a container image<\/li>\n<li>Creating a complete cloud infrastructure to support the service<\/li>\n<li>Deploy the image on the infrastructure and start the service<\/li>\n<\/ol>\n<p>If this is not like magic, I wonder what that is.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Destroying Cloud Infrastructure<\/h2>\n\n\n\n<p>The last step is to destroy the entire infrastructure such that we don&#8217;t incur costs for those tests. The only thing that is required is to run the following Terraform command:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>terraform destroy<\/code><\/pre><\/div>\n\n\n\n<p>Just like with\u00a0<code>terraform apply<\/code>, Terraform will check the current state of the cloud infrastructure (which is defined in the <code>terraform.tfstate<\/code> JSON file), will show all the resources that will be destroyed, and ask the user to confirm that they want to proceed by answering\u00a0<code>yes<\/code>:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy.jpg\" alt=\"\" width=\"1352\" height=\"1770\" class=\"alignnone size-full wp-image-3782\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy.jpg 1352w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy-229x300.jpg 229w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy-782x1024.jpg 782w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy-768x1005.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/terraform_destroy-1173x1536.jpg 1173w\" sizes=\"auto, (max-width: 1352px) 100vw, 1352px\" \/><\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Linter<\/h2>\n\n\n\n<p>I would recommend that you always run your Terraform through a linter. There are several of them existing, none of them are mutually exclusive. Three popular ones are <a href=\"https:\/\/github.com\/terraform-linters\/tflint\">tflint<\/a>, <a href=\"https:\/\/github.com\/bridgecrewio\/checkov\">Checkov<\/a> and <a href=\"https:\/\/github.com\/aquasecurity\/trivy\">Trivy<\/a>. Checkov and Trivy are more focused on security risks.\u00a0<\/p>\n<p>For this blog post, I will only focus on <code>tflint<\/code>. Once you installed it, you can run it easily from your terminal:<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism line-numbers lang-plain\"><code>tflint<\/code><\/pre><\/div>\n\n\n\n<p style=\"text-align: left;\">If I run that command from the <code>\/terraform\/deploy\/<\/code> folder, and if I remove the Terraform version from the Terraform block,\u00a0<code>tflint<\/code> will return the following error:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint.jpg\" alt=\"\" width=\"1820\" height=\"438\" class=\"alignnone size-full wp-image-3784\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint.jpg 1820w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint-300x72.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint-1024x246.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint-768x185.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/tflint-1536x370.jpg 1536w\" sizes=\"auto, (max-width: 1820px) 100vw, 1820px\" \/><\/a><\/p>\n<p>You can then <a href=\"https:\/\/github.com\/terraform-linters\/tflint-ruleset-terraform\/blob\/v0.4.0\/docs\/rules\/terraform_required_version.md\">follow the link to the Github documentation<\/a> to understand what the error means and how to fix it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Run Linter every time you update your repository <\/h3>\n\n\n\n<p>The final step is to create a new <a href=\"https:\/\/docs.github.com\/en\/actions\">Github Action<\/a> that will be triggered every time the <code>main<\/code> is modified. I simply had to use the <code>setup-tflint<\/code> <a href=\"https:\/\/github.com\/marketplace\/actions\/setup-tflint\">action from the marketplace<\/a>, add it to my repository, and <a href=\"https:\/\/github.com\/fgiasson\/literate-en-fr-translation-service\/blob\/main\/.github\/workflows\/tflint.yaml\">to push it to \u00a0GitHub<\/a> to run it every time the\u00a0<code>main<\/code> branch is modified.\u00a0<\/p>\n<p><a href=\"https:\/\/github.com\/fgiasson\/literate-en-fr-translation-service\/actions\/runs\/6111146130\/job\/16585722119\">Here is what it looks like when it runs<\/a>:<\/p>\n<p><a href=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-scaled.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-scaled.jpg\" alt=\"\" width=\"2560\" height=\"1345\" class=\"size-full wp-image-3785 aligncenter\" srcset=\"https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-scaled.jpg 2560w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-300x158.jpg 300w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-1024x538.jpg 1024w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-768x403.jpg 768w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-1536x807.jpg 1536w, https:\/\/fgiasson.com\/blog\/wp-content\/uploads\/2023\/09\/flint_google_action-2048x1076.jpg 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/a><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion<\/h3>\n\n\n\n<p>This is what finalizes the series of blog posts related to the creation of an English\/French translation web service endpoint using Hugging Face models.<\/p>\n<p>As we can see, the current state state of the DevOps and machine learning echo system enables us to create powerful web services, in very little amount of time, with minimal efforts, while following engineering best practices.<\/p>\n<p>None of this would have been as simple and fast just a few years ago. Just think about the amount of work necessary, by millions of people and thousands of business over the years to enable Fred to spawn a translation service in the Cloud, that anyone can access, with a single command in my laptop terminal.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In a previous blog post, I explained how we can easily deploy Hugging Face models in Docker containers. In this new post, I will explain how we can easily deploy that container in Azure using Terraform. At the end of this article, we will have end-to-end process that creates a translation service, containerize, deploy in [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[309],"tags":[317,310,311,289,316,315],"class_list":["post-3766","post","type-post","status-publish","format-standard","hentry","category-mlops","tag-devops","tag-docker","tag-huggingface","tag-machinelearning","tag-mlopds","tag-terraform"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3766","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=3766"}],"version-history":[{"count":18,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3766\/revisions"}],"predecessor-version":[{"id":3789,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3766\/revisions\/3789"}],"wp:attachment":[{"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=3766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=3766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fgiasson.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=3766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}