How to host multiple sites on Azure web app for Containers using docker compose - docker-compose

I would like to use a docker compose file to deploy multiple public end points for our Linux hosted site.
We already have a deployed site that has images stored on a private ACR and is hosted on an Azure App Service (using Web App for Containers). It is deployed via Azure DevOps and works well.
We would however, like to use the same site to host an additional component, an api so that we would then end up with these endpoints:
https://www.example.com - the main site
https://www.example.com/api - the api
We would like to avoid a second app service or a subdomain if possible. The architecture we prefer is to use the same https certificate and ports (443) to host the api. The web site and api share a similar code base.
In the standard app service world, we could easily have deployed a virtual directory to the main app which is simple enough.
This model though seems to be more complicated when using containers.
How can we go about this? I've already had a look at this documentation: https://learn.microsoft.com/en-us/azure/app-service/containers/tutorial-multi-container-app. However, in this example, the second container is a private one - which doesn't get exposed.
Should we use a docker compose file (example please)? Or alternatively, is there a way we can use the Azure DevOps task to deploy to a viritual directory in the way that i would like. This is the task we are using for the single container deployment:
https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/deploy/azure-rm-web-app-containers?view=azure-devops

For your requirements, the Web App For Container is also a type of Web App service, and as you see, it only can expose one container to the outside(the Internet) and others are private. So if you want to use the multi-containers Web App to deploy the images to access multiple endpoints such as the main site and the API site, then it's impossible to make your purpose come true.
According to the feature of the Web App that it only exposes one container to the outside, what you can do to achieve your purpose is that creates only one image and route to the endpoints yourself in the code or through a tool, such as the Nginx. Then deploy it to the Web App for Container. Only in this way, you can access multiple endpoints from only one App service..

Related

Service name with url pattern

I currently have a service name matrix-calculator
My service is deployed as
http://matrix-calcualtor.company.prod.com/api/v1/calculate
Im not sure if this is the best way to have this url, as i would like to have the following as it allows local dev development when running multiple services
http://matrix-calcualtor.company.prod.com/matrix-calculator/api/v1/matrix
Thoughts

injected db credentials change when I deploy new app version to cloud

I deploy a web app to a local cloudfoundry environment. As a database service for my DEV environment I have chosen a Marketplace service google-cloudsql-postgres with the plan postgres-db-f1-micro. Using the Web UI I created an instance with the name myapp-test-database and mentioned it in the CF Manifest:
applications:
- name: myapp-test
services:
- myapp-test-database
At first, all is fine. I can even redeploy the existing artifact. However, when I build a new version of my app and push it to CF, the injected credentials are updated and the app can no longer access the tables:
PSQLException: ERROR: permission denied for table
The tables are still there, but they're owned by the previous user. They were automatically created by the ORM in the public schema.
While the -OLD application still exists I can retrieve the old username/password from the CF Web UI or $VCAP_SERVICES and drop the tables.
Is this all because of Rolling App Deployments? But then there should be a lot of complaints.
If you are strictly doing a cf push (or restart/restage), the broker isn't involved (Cloud Controller doesn't talk to it), and service credentials won't change.
The only action through cf commands that can modify your credentials is doing an unbind followed by a bind. Many, but not all, service brokers will throw away credentials on unbind and provide new, unique credentials for a bind. This is often desirable so that you can rotate credentials if credentials are compromised.
Where this can be a problem is if you have custom scripts or cf cli plugins to implement rolling deployments. Most tools like this will use two separate application instances, which means you'll have two separate bindings and two separate sets of credentials.
If you must have one set of credentials you can use a service key to work around this. Service keys are like bindings but not associated with an application in CloudFoundry.
The downside of the service key is that it's not automatically exposed to your application, like a binding, through $VCAP_SERVICES. To workaround this, you can pass the service key creds into a user-provided service and then bind that to your application, or you can pass them into your application through other environment variables, like DB_URL.
The other option is to switch away from using scripts and cf cli plugins for blue/green deployment and to use the support that is now built into Cloud Foundry. With cf cli version 7+, cf push has a --strategy option which can be set to rolling to perform a rolling deployment. This does not create multiple application instances and so there would only ever exist one service binding and one set of credentials.
Request a static username using the extra bind parameter "username":
cf bind-service my-app-test-CANDIDATE myapp-test-database -c "{\"username\":\"myuser\"}"
With cf7+ it's possible to add parameters to the manifest:
applications:
- name: myapp-test
services:
- name: myapp-test-database
parameters: { "username": "myuser" }
https://docs.cloudfoundry.org/devguide/services/application-binding.html#arbitrary-params-binding
Note: Arbitrary parameters are not supported in app manifests in cf CLI v6.x. Arbitrary parameters are supported in app manifests in cf CLI v7.0 and later.
However, I can't find the new syntax here: https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html#services-block . The syntax I use comes from some other SO question.

How to get multi container application's URL from Docker Compose Task in Azure Pipeline?

I've configured multi container using Docker Compose Task in Azure Pipeline. I could not able to get URL for the multi container application.
Do I need to configure the app service along with the docker compose task?
Please guide!!!
UPDATE
In order to get the application's URL from DockerCompose Task, Can make use of Azure CLI commands provided in the following documentation link suggested by Merlin Liang - MSFT
https://learn.microsoft.com/en-us/azure/container-instances/container-instances-multi-container-yaml#view-deployment-state
Not sure here which URL is you are looking for.
1) If what you means is the browsing URL of your APP, you could find it in Overview tab of app service:
Even though it is a multi-container app, this URL has fixed format, and do not be affected by anything:
http://<your-app-name>.azurewebsites.net
2) If what you want is a integrate URL which used to notify/update the app service once a new version of the image is available.
Just go Container settings => Continuous Deployment => Webhook URL:
Do I need to configure the app service along with the docker compose
task?
This depend on your actual demand. It is not necessary in most scenarios.
Docker compose task used to orchestration your container. Based on your last SO ticket, you just run service. In fact, in Azure Web App for Containers task. it integrate this part:
If you think here it can not satisfied your usage, you could make use of Docker compose task.
Updated in 2020/3/2:
If someone just build and push the containerization app into ACR, without any integrate with Azure app service. At this time, the browsing url should be look like localhost:<port>.
To get exact host name and ip address, just run below commands to get:
az container show --resource-group myResourceGroup --name myContainerGroup --output table

What is the difference between an Endpoints service and AppEngine service when they have the same URL?

I have two services in Endpoints in GCP to host two APIs
They are
Service A
and
Service B
Service A's host is
projectid.appspot.com
Service B's host is
test-dot-projectid.appspot.com
When I deploy my app using gcloud app deploy Service A's test service in
appengine my app.yaml looks like this
runtime: go
env: flex
service: test
endpoints_api_service:
name: projectid.appspot.com
rollout_strategy: managed
handlers:
- url: .* #mandatory
secure: always #deprecated in flex environment
redirect_http_response_code: 301 #optional
script: _go_app #mandatory
From my understanding, the app has been deployed to Service A's URL
projectid.appspot.com but with the subdomain test so test-dot-projectid.appspot.com
However is this now not technically deploying to Service B on a default service i.e.
test-dot-projectid.appspot.com
Is this not interfering with deploying on service A with service test? What is the difference?
My understanding is: if service A is "projectid.appspot.com". Only "projectid.appspot.com" will be routed to A, not "test.projectid.appspot.com". So you can safely deploy sevice B with "test.projectid.appspot.com". But I am not sure. Have you tried it?
When having an application with multiple services, the service names must be configured and must be unique.
The default project is not required to have a service name. This is true when a single service for an application exists.
When having multiple services (Service A, Service B), the application must be first deployed to the default service. After which, each service must have their own app.yaml file.
It is recommended for each service to be configured with a unique service name to prevent miscommunication. If a unique service name is not configured for each service, by default, it will deploy to the default service’s URL. In your case, since the default service URL and Service A’s service URL are the same, it is causing a conflict.
To deploy to a specific services’ service name, you will need to specify the service name and its app.yaml file.
For more information, please refer to:
Planning your directory structure and app.yaml naming:
https://cloud.google.com/appengine/docs/flexible/go/configuration-files#directory_structure
How to deploy to multiple or specific service in a multi-service environment:
https://cloud.google.com/appengine/docs/flexible/go/testing-and-deploying-your-app#deploying_multiple_services
App Engine is made up of application resources that are made up of one or more services (previously known as modules). Each service is code independent and can run different runtimes and you deploy versions of that service. The URL is how your application is accessed either via a user request or an API call to the service.
For more information, please see https://cloud.google.com/appengine/docs/standard/python/microservices-on-app-engine#app_engine_services_as_microservices
Endpoints are part of the Cloud Endpoints Framework service offered by Google Cloud to manage, deploy, maintain and secure your API. In App Engine, Endpoint framework is only supported on Python 2.7 and Java runtime environments. It is a tool that allows you to generate REST API and client libraries for your application.
For more information, please see
https://cloud.google.com/endpoints/docs/frameworks/about-cloud-endpoints-frameworks

What's the hostname of openshift master server for internal access?

If I want to access the REST API of the openshift master server from anywhere in my company I use https://master.test04.otc-test.company.com:8443 which works just fine.
Now I'm writing an admin application that is accessing the REST API and is deployed in this openshift cluster. Is there a generic name or environment variable in openshift to get the hostname of the master server?
Background: My admin application will be deployed on multiple openshift clusters which do not have the same URL. It would be very handy to have them autodiscover the hostname of the current master server instead of configuring this value for every deployment.
Use environment variables:
https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT
In the container, unless service account details are not being mounted, you can also access the directory:
/var/run/secrets/kubernetes.io/serviceaccount
In this you can then find a token file which contains the access token for the service account the container runs as. This means you can create a separate service account for the application in that project, and use RBAC to control what it can do via the REST API.
That same directory also has a namespace file so you know what project the container is running in, and files with certificates to use when accessing the REST API over a secure connection.
This is the recommended approach, rather than trying to pass an access token to your application through its configuration.
Note that in OpenShift 4, if you need to access the OAuth server endpoint, it is on a separate URL to what the REST API is. In 3.X, they were on the same URL.
In 4.0, you can access the path /.well-known/oauth-authorization-server on the REST API URL, to get information about the separate OAuth server endpoint.
For additional information on giving REST API access to an application via a service account, see:
https://cookbook.openshift.org/users-and-role-based-access-control/how-do-i-enable-rest-api-access-for-an-application.html
Note that that page currently says you can use https://openshift.default.svc.cluster.local as URL, but this doesn't work in OpenShift 4.