I setup a GraphQL playground listening on port 4000.
So I added the following Traefik labels:
graphql:
restart: unless-stopped
labels:
- traefik.enable=true
- "traefik.http.routers.${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}-graphql.rule=Host(`graphql.${CI_ENVIRONMENT_HOST}`)"
- traefik.http.routers.${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}-graphql.tls.certresolver=letsencrypt
- traefik.http.services.${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}-graphql.loadbalancer.server.port=4000
This is working when I try to get graphql.site.com.
Now I want it to match site.com/graphql, so I changed the router label to this:
"traefik.http.routers.${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}-graphql.rule=Host(`${CI_ENVIRONMENT_HOST}`) && Path(`/graphql`)"
And with this configuration, I have a 404 error on site.com/graphql.
What did I miss?
In my opinion there is no backend application listening on the path /graphql.
Solution 1:
Make backend application (GraphQL) listen on path /graphql.
Probably you should also use PathPrefix(`/graphql`) instead of Path(`/graphql`)
Solution2:
Use traefik StripPrefix, which removes prefixes from the path before forwarding the request.
Use these labels.:
- "traefik.http.routers.${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}-graphql.rule=Host(`${CI_ENVIRONMENT_HOST}`)"
- "traefik.http.middlewares.stripprefix-graphql.stripprefix.prefixes=/graphql"
- "traefik.http.routers.${CI_PROJECT_PATH_SLUG}-${CI_ENVIRONMENT_SLUG}-graphql.middlewares=stripprefix-graphql#docker"
In case the backend is serving assets (e.g., images or Javascript files) you need to implement additional changes on your backend:
More info here: https://docs.traefik.io/middlewares/stripprefix/.
Hope this helps.
How does Path('') work?
(the traefik docs dont explain it)
I'd like to create a traefik ingress rule that finds a substring in a host name, e.g. I would like to match api in all 3 these examples:
mysite.com/subroute1/api/get
mysite.com/subroute2/api/post
mysite.com/subroute2/api/post
PathPrefix will not work because the prefix is different for subroute1, subroute2 and subroute3.
Can I use Path('/api'), will it work for all 3 subroutes? (or isn't there something like a PathContains('/api'))?
Related
I've an issue wit a redirect-middleware in traefik V2.
We want to add a trailing-slash to a sublocation and then remove
the path with a PathPrefix-Rule to get correct paths from the docker service. (MkDOCS)
We defined the rule in dynamic_conf.toml for traefik as a general middleware.:
[...]
[http.middlewares.add-trailing-slash.redirectregex]
regex= "(https?://[^/]+/[a-z0-9_]+)$$"
replacement= "$${1}/"
permanent = true
[...]
At the moment this is our label-file included with docker-run:
traefik.enable=true
traefik.http.routers.dockerservice.entryPoints=websecure
traefik.http.routers.dockerservice.rule=PathPrefix(`/dockerservice`)
traefik.http.routers.dockerservice.tls=true
traefik.http.middlewares.dockerservice-strip.stripprefix.prefixes=/dockerservice
traefik.http.routers.dockerservice.middlewares=add-trailing-slash#file,doc-strip
At https://regex101.com/ the rule seems to work fine for eg https://domain.tld/dockerservice
If the service is up and we navigate to https://domain.tld/dockerservice
it redirects to https://domain.tld/${1}/
The Variable is not expanded. Instead we get the 404-not found error (as expected because a service route with this name does not exists in our traefik setup)
So the trailing-slash is added as desired, but the dockerservice-capture is not expanded.
We've also tried this as a #docker rule on the label_file for the docker-run command but the "error" remains.
We also tried this which we found on the web first (as #file in dyanmic_conf or #docker as label-file for docker run):
traefik.http.middlewares.add-trailing-slash.chain.middlewares=strip-prefix-1,strip-prefix-2
traefik.http.middlewares.strip-prefix-1.redirectregex.regex=^(https?://[^/]+/[a-z0-9_]+)$$
traefik.http.middlewares.strip-prefix-1.redirectregex.replacement=$${1}/
traefik.http.middlewares.strip-prefix-1.redirectregex.permanent=true
traefik.http.middlewares.strip-prefix-2.stripprefixregex.regex=/[a-z0-9_]+
We where trying with ${0} and multiple other attempts where made using double quotes, and single quotes or $-signs.
Our toolchain is as follows:
pushing into the git-repo on the master branach
gitlab-runner executes a .sh file with docker build and docker run command
label-file is provided in the git-repo
We would like to have a generic redirect for all services which have this middleware added
to add a trailing slash if only one Path-Element is added and the trailing slash is missng
So
https://domain.tld/dockerservice should redirect to https://domain.tld/dockerservice/
a Request like https://domain.tld/dockerservice/page should not be changed because
of the strip in the mkdocs container only /page is needed.
At this point we tried a lot and we don't know why traefik is not expanding the variable.
Anyone knows what we are doing wrong?
Best wishes
Exa.Byte
I've finally found a solution which suits well for our purpose:
I just used one $ sign in conjunction with two for the regex option.
added in dynamic.toml for traefik itself:
[http.middlewares.add-trailing-slash.redirectRegex]
regex= "(https?://[^/]+/[a-z0-9_]+)$$"
replacement= "${1}/"
permanent = true
lg
exa.byte
I have a local setup for SCDF with docker-compose.
I'm trying to understand how can I pass environment variables to a triggered task.
I tried via the 'Deployer properties' but it doesn't seem to work.
Ideally I would have liked to be able to set LOG4J2_APPENDER=PatternAppender in the UI...
If its not possible via the UI, what other options do I have?
I tried to add under 'enviroment' in the docker-compose.yml (where there are other vars):
but it also didnt work:
dataflow-server:
user: root
image: springcloud/spring-cloud-dataflow-server:${DATAFLOW_VERSION:-2.9.1}${BP_JVM_VERSION:-}
container_name: dataflow-server
ports:
- "9393:9393"
- "1142:1142"
environment:
# Set CLOSECONTEXTENABLED=true to ensure that the CRT launcher is closed.
- SPRING_CLOUD_DATAFLOW_APPLICATIONPROPERTIES_TASK_SPRING_CLOUD_TASK_CLOSECONTEXTENABLED=true
- LOG4J2_APPENDER=PatternAppender
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/dataflow
- SPRING_DATASOURCE_USERNAME=root
- SPRING_DATASOURCE_PASSWORD=rootpw
- SPRING_DATASOURCE_DRIVER_CLASS_NAME=org.mariadb.jdbc.Driver
# (Optionally) authenticate the default Docker Hub access for the App Metadata access.
#- SPRING_CLOUD_DATAFLOW_CONTAINER_REGISTRY_CONFIGURATIONS_DEFAULT_USER=${METADATA_DEFAULT_DOCKERHUB_USER}
#- SPRING_CLOUD_DATAFLOW_CONTAINER_REGISTRY_CONFIGURATIONS_DEFAULT_SECRET=${MET
In your snippet, you're passing the environment variable SPRING_CLOUD_TASK_CLOSECONTEXTENABLED with the value true to all tasks.
The same should work for LOG4J2_APPENDER, i.e. add the environment variable
SPRING_CLOUD_DATAFLOW_APPLICATIONPROPERTIES_TASK_LOG4J2_APPENDER=PatternAppender
to the environment variables of the Dataflow server.
Setting the environment variable as an application property (not a deployer property) in the UI should have the same effect.
splunkuniversalforwarder:
image: splunk/universalforwarder
environment:
- SPLUNK_START_ARGS=--accept-license
- SPLUNK_FORWARD_SERVER=ops-splunkhead02.dop.sfdc.net:9997
- SPLUNK_USER=root
- SPLUNK_PASSWORD=xxxx
ports:
- 9997:9997
I store the log flie in /var/logs/serviceLog.log (Not in the container but in the local machine)
I don't see the parameter to pass the file path;;; Seems like the splunk forwarder is running in the background and I just realized I never pass the log source variable to the container!
Does anyone perhaps have an idea?
you will need to add SPLUNK_ADD directive to your sample to specify the behavior.
you can use docker image related documentation to see multiples examples.
I wrote a ready to use splunk docker bootstrap project that will use SPLUNK_ADD to collect logs.
a short extract:
SPLUNK_ADD_2: 'monitor /var/log/app2/ -index docker_file -sourcetype _json'
I am trying to deploy a python Flask Application on Cloudfoundry but it fails.
It shows the output
The app cannot be mapped to route hello.cfapps.io because the route exists in a different space.
Please find the screenshot of the error
Here is what my travis.yml looks like:
stages:
- test
- deploy
language: python
python:
- '3.6'
env:
- PORT=8080
cache: pip
script: python hello.py &
jobs:
include:
- stage: test
install:
- pip install -r requirements.txt
- pip install -r tests/requirements_test.txt
script:
- python hello.py &
- python tests/test.py
- stage: deploy
deploy:
provider: cloudfoundry
username: vaibhavgupta0702#gmail.com
password:
secure: myencrytedpassword
api: https://api.run.pivotal.io
organization: Hello_Flask
space: development
on:
repo: vaibhavgupta0702/flask_helloWorld
Here is what my manifest.yml file looks like
---
applications:
- name: hello
memory: 128M
buildpacks:
- https://github.com/vaibhavgupta0702/flask_helloWorld.git
command: python hello.py &
timeout: 60
env:
PORT: 8080
I do not understand why the error is coming. Any help would be highly appreciated.
The app cannot be mapped to route hello.cfapps.io because the route exists in a different space.
This means exactly what it says. The domain cfapps.io is a shared domain which can be used by many people on the platform. When you see this error, it is telling you that someone else using the platform has already pushed an app which is utilizing that route.
There's a couple possibilities here:
Routes are scoped to a space. If you have multiple spaces, it's possible that the route in question could be used by an app in one of your other spaces. What you can do is run cf routes --orglevel. This will list all the routes in all the spaces under your organization. If you see the route hello listed under one of your spaces, simply run cf delete-route cfapps.io --hostname hello in the space where the route exists. That will delete it. Then deploy again.
Someone else is using the route. This means it would be in another org & space where you can't see it being used. In this case, there's not much you can do. You just need to pick another route or use a custom, private domain (note that custom, private domains require you to register a domain name & configure DNS as described here).
You can pick another route in a couple ways.
Use a random route. This works OK for testing, but not for anything where you want a consistent address. To use, just add random-route: true to your manifest.
Change your app name. By default, the route assigned to your app will be <app-name>.<default-domain>. Thus you get hello.cfapps.io because hello is your app name and cfapps.io is the default domain on PWS. If you change your app name to something unique, that'll result in a unique route that no one else is using.
Specifically define one or more routes. You can do this in your manifest.yml file. You need to add a routes: block and then add one or more routes.
Example:
---
...
routes:
- route: route1.example.com
- route: route2.example.com
- route: route3.example.com
I am looking at the code in eShopOnContainer under the docker-compose.override.yml. I can see a line in
volumes:
- ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}
webshoppingapigw:
environment:
- ASPNETCORE_ENVIRONMENT=Development
- IdentityUrl=http://identity.api #Local: You need to open your local dev-machine firewall at range 5100-5110.
ports:
- "5202:80"
volumes:
- ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}
What does the line in the volumes ${ESHOP_OCELOT_VOLUME_SPEC .. is? I would think it will create a volumes of something but the ${ESHOP_OCELOT_VOLUME_SPEC … I can't see where it define in the project even not inside the .env file.
When I went inside the docker-compose.override.prod, the line ${ESHOP_OCELOT_VOLUME not even there.
Currently I have exception running the sample code, therefore I tried to do follow the code from eShopOnContainer but code a simple version so I can easily to follow. I start doing the ApiGateway and building up from there.
I don't know is this question eligible to be asked. People here very fuzzy of the question.
volumes: - ./src/ApiGateways/Web.Bff.Shopping/apigw:${ESHOP_OCELOT_VOLUME_SPEC:-/app/configuration}
That means:
Mount the ./src/ApiGateways/Web.Bff.Shopping/apigw to the path mentioned by $ESHOP_OCELOT_VOLUME_SPEC
If $ESHOP_OCELOT_VOLUME_SPEC is empty (not defined), then use as a mount path /app/configuration.
That gives the opportunity to a user to override the default path by a path of his/her choosing.
docker run -e ESHOP_OCELOT_VOLUME_SPEC=/my/path ...
ESHOP_OCELOT_VOLUME_SPEC which is an environment variable. The variable value may be exported/set in some place of the code or in the instance. ESHOP_OCELOT_VOLUME_SPEC will be replaced with value, that's why you where not able to see ESHOP_OCELOT_VOLUME_SPEC in docker instead the value in ESHOP_OCELOT_VOLUME_SPEC.